UseCallback, same as useMemo hook, is useful in situation, when you want to improve performance of your app. Thanks to it, you can avoid useless renders, so app can works faster.
UseCallback returns memorized version of the callback function, that only changes if one of the dependencies has changed. This means, that if you have a parent component with children, they are rendering every time when parent is rendering. But you avoid children rendering if you pass to it function wrapped in useCallback hook, and at the same time wrap child component in React.memo higher-order component. Sounds confusing? Lets see it on example:
App.je component contains our parent component, named HookExample:
import React from 'react';
import HookExample from './components/hookExample.js';
function App() {
return (
<HookExample />
);
}
export default App;
So far, it’s easy. Now lets see what contains parent component:
Parent component contains counter state and changeCounter function, that changes counter value. It returns counter value and child, to which pass changeCounter function.
Now, each time when you click on +1 or -1 button you’ll see, that in console are logged two lines: one from parent component and one from child component. Imagine now, that you have 100 children in your parent component. Each of them is rendered, so each on them will log one line, but albo will make other calculations that you put in it. This takes some time and resources, and is unnecessary if any data passed to children are not change. So, as I mentioned earlier, you can avoid children rendering, and saving some time and resources by passing to them function wrapped in useCallback hook:
const changeCounter = useCallback(
(sign) => {
if (sign === "+") {
setCounter(c => c + 1);
}
else {
setCounter(c => c - 1);
}
}, [setCounter]
)
Remember also about wrapping child component in React.memo higher-order component:
Now if you click +1 or -1 button you’ll see, that only parent component logged its sentence to console, and child component don’t. UseCallback passed memorized version of function to child, and if it’s dependencies (in this case setCounter function) do not change, then child component will always receive the same props. Because you wrapped child component in React.memo higher-order component, which works similar to React.PureComponent, but is used only in functional components, when child component receive the same props as previous, React will skip rendering the component, and reuse the last rendered result.
According to documentation, “This method only exists as a performance optimization. Do not rely on it to “prevent” a render, as this can lead to bugs”.
I write code that (usually) works. I tame WordPress, learn React, explore the world of DevOps, and click around in the Linux console. I optimize code as a hobby, because laziness is the purest form of productivity. I do my best not to lose my mind somewhere between a bug and a deadline.