React Hooks (useCallback and useMemo)
Comrades.. There is a problem, I can not understand the chips of the useCallback and useMemo hooks. I have already read the doc and a couple of different articles, but there is no clear picture of what this is necessary for, what is the use of it, in what phase it happens. I would be grateful for any clear explanation.
2 answers
Let's start with useCallback
Let's write the simplest counter function.
function App() {
const [count, setCount] = useState(0);
return (
<div className="App">
<p>counter: {count}</p>
<button
onClick={_ => setCount(prevCount => prevCount + 1)}>
increment</button>
</div>
);
}
Let's add a function there that outputs the text
function App() {
const [count, setCount] = useState(0);
const helloConsole = _ => {
console.log("hi chaps :)");
};
helloConsole();
return (
<div className="App">
<p>counter: {count}</p>
<button
onClick={_ => setCount(prevCount => prevCount + 1)}>
increment</button>
</div>
);
}
Now, every time the counter is increased, this function helloConsole
will be re-created.
That is,
First render
function App() {
const count = 0;
const helloConsole = _ => {
console.log("hi chaps :)");
};
helloConsole();
//...
Second render
function App() {
const count = 1;
const helloConsole = _ => {
console.log("hi chaps :)");
};
helloConsole();
//...
Third render
function App() {
const count = 2;
const helloConsole = _ => {
console.log("hi chaps :)");
};
helloConsole();
//...
And the function helloConsole
from the first render is NOT equal to the function from the second render, etc. A new function is created for each render helloConsole
with a new link.
// 1 count ------- 2 count //
helloConsole !== helloConsole
And then you need to think about what will happen if you have a function on a real project that is recreated every time and makes certain calculations inside 500 lines of code. I think the performance of this component will drop.And even depending on the situation and the code, you can see it with the naked eye.
Solution
useCallback
Wrap your function in useCallback
and add an array dependencies.
const anyFunc = useCallback(() => {
// 500 строк кода
}, [dependencies]);
IMPORTANT NOTES
1.Don't use useCallback
without an array of dependencies.
const anyFunc = useCallback(() => {
// любой код
}, []);
You don'T have to write like that. Here you will lose more than you will get. If there is no dependency array, just write a function outside of the component. Something like that.
const anyFunc = () => {
// любой код
};
function App () { // наш компонент
This code is identical to useCallback
without the dependency array. I advise you to use the second approach if the array useCallback
is empty.
2.Don't use useCallback everywhere you can use.
const handleClick = useCallback(() => {
// обработать события клика
}, []);
Again, in this code, you will lose more than you will get. Your component will become slower.
Here here you can see how the component works with and without useCallback
Hook useMemo
Unlike useCallback
which only memoizes callbacks useMemo
memoizes everything.
const List = React.useMemo(() =>
listOfItems.map(item => ({
...item,
itemProp1: expensiveFunction(props.first),
itemProp2: anotherPriceyFunction(props.second)
})), [listOfItems]
)
Example taken from here
In this case, useMemo
returns an array.
In the link at the top that I specified written
If you implement useMemo too often in an application, it can harm the performance.
If you will use useMemo
frequently this can harm the performance of the application.
This means that the second remark that I wrote at the top for useCallback
is also relevant for useMemo
.
Also if you try to memoize the callback in useMemo it will be identical to using useCallback
useCallback(fn, deps) — это эквивалент useMemo(() => fn, deps).
useCallback
remembers the function and does not recreate it for optimization purposes.
useMemo
remembers the value and does not recalculate it (complex mathematical calculations), also for optimization.
It is used depending on what you need: a function or a value.