Why and How to use useCallback and React.memo

useCallback
function is used to prevent or restrict the re-creation of functions. One common case is using this function with React.memo
(or shouldComponentUpdate
in class based components) to improve the performance issues. This is especially crucial during rendering of large number of components needlessly.
In theory, we can use the trick mentioned above every time, but it does not always bring an optimal solution to performance. Be aware that there is an overhead of checking props for change in child components when memo
or shouldComponentUpdate
is used. Therefore the decision to prevent unnecessary renders of child components should only be applied when we are sure it will pay off.
In this story, I will give a simple React-Native example to show the effect of useCallback
when it is used with memo
in order to eliminate unnecessary renders of child components.
In the following example, a parent functional component has two different functions to be passed as parameters to its child components. While one of the methods is wrapped by useCallback
, the other function is not. Second child component takes the function wrapped by useCallback
as a parameter and uses memo
internally to discard re-rendering as long as props passed by parent do not change. That’s what we want!
Both the parent component and children components hold a counter
state and increments it via button clicks. The parent component also passes a button press handler function to be invoked when child components’ counter incrementing buttons are clicked.
Counter state change on parent component causes parent component to re-render. On each render, functions of parent component will be recreated if they are not wrapped by useCallback
. This results in a re-rendering of the first child component whenever the parent’s counter change, since it receives a different buttonPress
(child1ButtonPress
below in code snippet) function as prop each time parent renders. This is not the case for the second child component since it is always passed the same buttonPress
(child2ButtonPress
below in code snippet) function as prop, which is created only in the first rendering of the parent.

As can be seen in Demo Run above, Child1
is rendered each time parent re-renders; but it is not the case for Child2
thanks to using useCallback
for press handler in parent and memo
within the child itself. You can reach the whole code from following github repository.