I'm in the process of refactoring some of our components so I'm trying to incorporate memoization as some components may re-render with the same values (for example, hotlinked image URLs unless they are the same).
I have a simple component:
const CardHeader = props => {
// img is a stringand showAvatar is a boolean but it's always trueconst { ..., showAvatar, img } = props;
return (
<CardHeader><ListItem>
// AvatarImage shouldn't re-render if img is the same as previous
{showAvatar && <AvatarImage img={img} /></ListItem></CardHeader>
);
}
And then the AvatarImage:
const AvatarImage = React.memo(props => {
console.log("why is this still re-rendering when the img value hasn't changed?");
const { img } = props;
return (
<ListItemAvatar>
{img ?
<Avatar src={img} />
:
<Avatar>
Some initials
</Avatar>
}
</ListItemAvatar>
);
});
I have also tried passing in second argument of memo:
(prevProps, nextProps) => {
return true; // Don't re-render!
}
But the console.log still shows every time. I'm obviously missing something here or don't quite understand how this works. This component is a few levels down, but it passes in the img if it's available every time so I'd expect it to know that if the img was passed in the previous render and it's the same it knows not to re-render it again but for some reason it does?
Thanks all. It's much appreciated.
React.memo is a higher-order component that wraps a functional component and memoizes it, meaning that it only re-renders if one of its props has changed. If you want to prevent a component from re-rendering, you can use it like this:
Copy code const MyComponent = React.memo(props => { // component implementation here });
However, the problem you are experiencing might be caused by the fact that the props being passed to the AvatarImage component are not being properly compared by the default prop comparison function that React.memo uses. By default, React.memo compares props using a shallow comparison, meaning that it only checks if the props are the same object, not if they have the same content.
To fix this, you can pass a custom comparison function as the second argument to React.memo that compares the props in a way that makes sense for your component. For example, if you want to compare the img prop using a strict equality check (===), you can do the following:
const AvatarImage = React.memo(props => { console.log("why is this still re-rendering when the img value hasn't changed?"); const { img } = props; return ( <ListItemAvatar> {img ? ( <Avatar src={img} /> ) : ( <Avatar>Some initials</Avatar> )} </ListItemAvatar> ); }, (prevProps, nextProps) => { return prevProps.img === nextProps.img; });
This will prevent the AvatarImage component from re-rendering if the img prop has not changed.