Reputation: 514
I have a function called onRemove
that is written like this:
const [todos, setTodos] = useState(todoData);
const onRemove = useCallback(
(id) => {
setTodos(todos.filter((todo) => todo.id !== id));
},
[todos]
);
Then I noticed that changing it functional resulted in shorter rendering time.
const onRemove = useCallback(
(id) => {
setTodos(todos => todos.filter((todo) => todo.id !== id));
},
[]
);
My question is:
setState()
?Upvotes: 10
Views: 10450
Reputation: 169
setState()
useCallback()
to memoize the function onRemove()
, so it won't be created every time the component re-render
.onRemove()
will be created only once - when the component mountsfunctional
setState()
is used to escapeclosure
import React, { useState, useEffect } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
console.log('render');
useEffect(() => {
console.log('componentDidUpdate')
const id = setInterval(() => {
setCount(count) // count is always 0 because the variable count is closured
}, 1000);
return () => {
clearInterval(id);
console.log('clean');
}
}, []); // run only once when the component mounts
return (
<h1>
{count}
</h1>
)
}
export default Counter;
setState()
to read fresh stateimport React, { useState, useEffect } from 'react';
const Counter = () => {
const [count, setCount] = useState(0);
console.log('render');
useEffect(() => {
console.log('componentDidUpdate')
const id = setInterval(() => {
setCount(count => count + 1); // read fresh value of count
}, 1000);
return () => {
clearInterval(id);
console.log('clean');
}
}, []); // run only once when the component mounts
return (
<h1>
{count}
</h1>
)
}
export default Counter;
Upvotes: 2
Reputation: 116
When using hooks, you have to define an array of dependencies which when changes re-runs the function inside the hook.
In your first case its todos
because you are using it to filter. Now what happens is when you setTodos with a new array your dependency todos changes which again re-runs and setTodos sets new todos. It actually runs indefinitely which is not what you want. You shouldn't define dependency to a hook whose value is being set inside it.
In your second case there aren't any dependency so even if you setTodos it won't re-run. The setTodos
hook provides its current value in its callback parameter which you can use to avoid adding dependency. Also, this way is the right way to do it.
Upvotes: 0
Reputation: 282160
In the first case when you add todos as a dependency to useCallback
, the function will be recreated again each time you call it since it is setting todos state itself and hence will not be optimized for memoization
In the second case, you are using the callback version os state updater which essentially will provide you the previous state as an argument to callback and the function will be only created once.
This should be the preferred approach
To know more about the advantages of functional setState, please check the linked post:
Upvotes: 2