When NOT to use React.memo ?
Lets understand, what is memo in react. If you are working with React, you may have heard or used React.memo
in your code. According to the official React documentation, we can use memo
as follows:
Wrap a component in memo to get a memoized version of that component. This memoized version of your component will usually not be re-rendered when its parent component is re-rendered, as long as its props have not changed.
So, most of the time, we think that if a component is wrapped in React.memo
, it will not re-render if its props have not changed. However, this is not always the case, as React may still re-render it.
Before moving ahead, let’s see how we usually use React.memo
in general.
In the above example, we have two components: the App
component and the MemoisedComponent
, which is a child of the App
component. This MemoisedComponent
is wrapped with memo
. So, if you run the code, you will notice that as the counter increases, we are updating the count
state. When the user clicks the increase the count
button, the count state gets updated and the App
component gets rerendered. However, since App
is the parent component to the MemoisedComponent
, if we don't memoize the child component, it will also get rerendered. But, as we wrapped the child component and the props we pass in it are static and not changing, this child component is not rerendering.
(Check by Opening the codesandbox in full mode)
Case 1: Passing Object as a Prop
Most of the time, we pass props. Although we use Redux or context to solve prop drilling, we still pass props from parent to child for some component-level problems. If the props are static or primitive, using React.memo
for the child component will solve the problem. However, problems arise when the prop is not static and is an object.
If the parent component is rerendered, the object in it will also get a new reference. When we use memo
, React compares the props with Object.is
, which is a shallow equality comparison.
Object.is(5,5) // true
Object.is({demo: "demo"}, {demo: "demo}) //false
Object.is({},{}) // false
So, when parent component rerender and we have object type props passed to the child component then using memo
doesn’t solve our problem. Because, value of object will be new and child component will re-render. So, using React.memo
to child component which takes object as a props doesn’t solve the re-rendering of child problem.
How to solve this?
Remember , useMemo
!, thats what we will be using here!
Lets take a look at following example.
(Recommended opening in codesandbox in full view mode)
In the above example, we are passing the object userDetails
as a prop. However, in the parent component, we have memoized its value and passed it to the child component. Therefore, if the parent component rerenders, the child will not rerender unless the values of name
and data
change.
If your child component only needs a specific property from the larger object, then destructuring it and passing only the required props is a better idea.
Case 2: Passing Function as Props
As an object gets a new reference, as we saw above, any function that is defined inside a component and passed to the child component as a prop will also get a new reference as the parent component rerenders. So, wrapping the child component in memo
will not directly solve our problem. We need to make the functional reference the same.
How to solve this?
We can use useCallback
hook to solve this problem. Lets take a look at following example.
In the above example, the handleClick
function is passed as a prop and assigned to the click
event on the button in the ButtonComponent
. However, the handleClick
function is wrapped in useCallback
. Therefore, even though the value of count
changes, the ButtonComponent
will not rerender.
Case 3: When Component is not Pure.
In React, a pure component is a component that only depends on the value of its props and value to render. It does not depend on any other variables or data outside of its scope. Pure components are intended to be lightweight and efficient, as they can be memoized by React to prevent unnecessary re-rendering.
To create a pure component in React, you can either extend the React.PureComponent
class or use the React.memo
higher-order component. By doing so, React will automatically compare the props and state of the component and only re-render if they have changed.
Overall, pure components should be used when possible to improve performance and decrease unnecessary re-renders.
Case 4: If it is not necessary, not to use it.
If you know that props are not going to be same.
Sometimes, we have props which we are aware that will not be same any how whatever be the case. In such times, using extensively memoisation just add extra layer of props comparison check which will not improve expected performance. So, in such cases, it is better to not use it.
All Component should not be pure.
It is important to note that not all components should be pure. If a component depends on data outside of its scope, such as global state or user input, it may need to re-render even if its props and state have not changed. Additionally, if a component is expensive to render, such as a large list or complex chart, it may not be worth the performance gains to make it pure.