In my functional React component, I have a function that is used both on component mount and in some child event:
const [count, setCount] = useState(0);
const myFunction = useCallback(() => {
// do something with count, such as a fetch or console.log for example
}, [])
useEffect(() => {
myFunction()
}, [myFunction])
return (
<button onClick={myFunction}>
myButton
</button>
)
myFunction
must be called on mount and when the button is clicked. However, the classic React way of doing this implies to declare count
as a dependency in useCallback
, which would trigger a call of myFunction
each time count
is updated by another part of the program, which I do not want. count
must be able to be updated without triggering myFunction
.
I cannot find a clean solution for doing this. Is there one? Or should I write my code a different way? What's the best way to deal with this situation?
CodePudding user response:
For your specific example, there's a simple solution. Instead of using the count
state variable inside of useCallback
, and therefore making it a dependency of the useCallback
hook, you could just use the callback parameter of the state updater function. So instead of:
const myFunction = useCallback(() => {
setCount(count 1)
}, [])
You could write it like this:
const myFunction = useCallback(() => {
setCount((prevCount) => prevCount 1)
}, [])
Another way, for more complex instances, would be to use the useReducer
hook instead of useState
. Since you would be using useReducer
's dispatch
function to update the state, there wouldn't any need to have the state
as a dependency in the useCallback
hook.
const [count, dispatch] = useReducer((state, action) => {
switch (action.type) {
case "INCREMENT":
return state action.by;
default:
return state;
}
}, 0);
const myFunction = useCallback(() => {
dispatch({ type: "INCREMENT", by: 1 });
}, []);
useEffect(() => {
myFunction();
}, [myFunction]);
return (
<div>
<p>{count}</p>
<button onClick={myFunction}>myButton</button>
</div>
);
CodePudding user response:
Use React functional updates for setState
:
setCount(count => count 1);
This way you do not need to add count
to dependencies.