paljakka
全ての投稿に戻る

How to use React useCallback hook

公開日 2024-09-29

This week I'm returning to React hooks. I've decided to cover the most useful hooks to remind myself how they work and if there is something new. I work with React every day, but I only use a handful of hooks on a regular basis. So, I'm going to go through all of the hooks and provide some small examples. I think it will be a helpful exercise for me and hopefully for others as well.

Introduction to useCallback

The useCallback hook is a valuable tool for optimizing the performance of your React application. By memoizing callback functions with this hook, you can avoid unnecessary re-renders and improve the overall performance of your app. I wrote an article earlier this year on custom hooks that briefly covers different types of hooks, including useCallback. If you're interested in learning more, you can check out that article.

What is useCallback?

It is a function that takes two arguments, a callback function and an array of dependencies. If you are familiar with the useEffect hook, the structure of useCallback is similar. The useCallback will return a memoized version of the callback function, which means that it will only be re-created if one of the dependencies in the array changes. This ensures that the callback function always has the most up-to-date value, and it prevents unnecessary re-renders in the child component where the callback is used.

If you are familiar with the useMemo hook, you might be wondering what the difference is between the two. One big difference is that the useCallback hook is specifically for memoizing callback functions, while the useMemo hook is for memoizing arbitrary values. But overall, both hooks help you optimize your React components by memoizing values and avoiding unnecessary re-renders, just with a different approach.

How to use

The useCallback hook can help optimize your React component's performance by memoizing your callback functions. To use it, just call the hook within your functional component and pass it the callback function and its dependencies as arguments. Then use the returned value from the hook as the callback function in your component. useCallback can be especially useful in situations where a callback function is used often and is likely to be recreated on every render.

1. Basic example

import { useCallback } from 'react'; const AwesomeReactComponent = () => { const myCallback = useCallback(() => { console.log("I'm callback"); }, []); return <button onClick={myCallback}>ClickClick</button>; };

In this example, the useCallback hook is called with a callback function and an empty array of dependencies. The returned value from the hook is then used as the callback for the onClick event of the button element.

2. Using together with useState and useEffect

// child component function LargeListOfRecipes({ searchTerm, onItemClick }) const items = useSearchRecipes(searchTerm); const map = item => <div onClick={onItemClick}>{item}</div>; return <div>{items.map(map)}</div>; } export default React.memo(LargeListOfRecipes);
import { useCallback } from 'react'; export function Recipes({ searchTerm }) { const onItemClick = useCallback( (evt) => { console.log(`You searched ${searchTerm}`); }, [searchTerm], ); return ( <LargeListOfRecipes searchTerm={searchTerm} onItemClick={onItemClick} /> ); }

Drawbacks

It is important to avoid overusing the useCallback hook in order to avoid potential drawbacks. One such drawback is that it might add complexity to your code, particularly in situations where it does not provide any performance benefits. You should only do performance optimization, if you are performing heavy computations on your app and you need to memoize your values.

Conclusion

The useCallback hook is similar to the useMemo hook in that it can be used to optimize the performance of your functional components by memoizing values. However, the useCallback hook memoizes functions instead of arbitrary values. This can help prevent the recreation of the callback function on every render, which can avoid unnecessary re-renders and improve the overall efficiency of your application.

It is important to note that optimization should always be approached with caution. Before embarking on any optimization efforts, it is essential to measure or profile the performance of your components to ensure that the optimization will be worthwhile. Optimization can increase the complexity of your code, and as a developer, you should always carefully consider the potential tradeoffs before proceeding. By being mindful of these considerations, you can ensure that your optimization efforts are effective and efficient.