'Can someone please tell me what am I doing wrong here? [React hooks]
I am trying to use the useDebounce hook in the handleChange function. But I am getting the following error
React Hook "useDebounce" is called in function "handleChange" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. (react-hooks/rules-of-hooks)
The code is as follows
import "./styles.css";
import { useEffect, useState } from 'react'
function useDebounce(value, delay) {
const [debouncedValue, setDebouncedValue] = useState(value)
useEffect(() => {
const timer = setTimeout(() => setDebouncedValue(value), delay || 500)
return () => {
clearTimeout(timer)
}
}, [value, delay])
return debouncedValue
}
const handleChange = (e) => {
let debouncedValue = useDebounce(e.target.value, 500);
console.log('debouncedValue', debouncedValue);
}
export default function App() {
return (
<div className="App">
<input type="text" placeholder="Search" onChange={(e) => {handleChange(e)}} />
</div>
);
}
Request if someone can shed some light as to what am I doing wrong here.
Solution 1:[1]
Issue
Like the error states, it's invalid to call React hooks in callbacks.
See Rules of Hooks
- Don’t call Hooks inside loops, conditions, or nested functions.
- Don’t call Hooks from regular JavaScript functions.
Solution
It seems like you are really wanting to debounce the handleChange callback handler.
Import a debouncing utility or create your own simple debounce higher order function.
Example:
const debounce = (fn, delay) => {
let timerId;
return (...args) => {
clearTimeout(timerId);
timerId = setTimeout(() => fn(...args), delay);
}
};
Usage:
export default function App() {
const [value, setValue] = useState(value);
const handleChange = e => {
setValue(e.target.value);
}
const debouncedHandler = debounce(handleChange, 500);
return (
<div className="App">
<input type="text" placeholder="Search" onChange={debouncedHandler} />
</div>
);
}
Solution 2:[2]
Hooks in React can only be called from React components or from other hooks.
React seems to validate hooks/components via their name scheme.
I.E. - hooks start with "use", components start with an uppercase letter.
Check out React's rules of hooks section regarding this.
So what's heppening here is that you are trying to use your custom useDebounce hook in a regular function.
Which would be the equivalent of trying to use useState or useEffect outside of a React component, and will produce the same error.
The solution is to either change the naming schemes or the structure of the code.
Solution 3:[3]
Try like this
import React, { useState, useEffect } from 'react';
function useDebounce(value, delay) {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const timer = setTimeout(() => setDebouncedValue(value), delay || 500);
return () => {
clearTimeout(timer);
};
}, [value, delay]);
return debouncedValue;
}
export default function App() {
const [term, setTerm] = React.useState('');
const debouncedValue = useDebounce(term, 500);
const handleChange = (e) => {
setTerm(e.target.value);
console.log('debouncedValue', debouncedValue);
};
return (
<div className="App">
<input
type="text"
placeholder="Search"
onChange={(e) => {
handleChange(e);
}}
/>
{debouncedValue}
</div>
);
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Drew Reese |
| Solution 2 | tomleb |
| Solution 3 | Hakob Sargsyan |
