Reputation: 97
I'm trying to reduce unnecessary rendering in child components. When a child component trigger a state modification all others unaffected components get re-rendered (in virtual DOM of course). I'm using React.memo but if I let the comparison to React.memo the renders are the same as if I wasn't using it.
To investigate the problem I tried to console.log the props.
The first component render a list of components based on props and on a template from another file.
const List = props => {
return (
<div id="List">
{template[props.status].map(
el =>
<ListItem
activeClass={props.active === el.type ? 'active' : ''}
handleClick={props.handleClick}
key={el.type}
itemType={el.type}
text={el.text} />
) }
</div>
)
}
I'm starting using memo in the ListItem component
const ListItem = React.memo( props => {
return (
<button
className={props.activeClass}
onClick={props.handleClick}
title={props.itemType}
value={props.itemType} >
{props.text}
</button>
)
}, (prevProps, nextProps) => {
prevProps === nextProps };
Whit this I get the same renders as if I wasn't using React.memo, so I console.log every single props.
prevProps === nextProps //false
prevProps.itemType === nextProps.itemType //true
prevProps.text === nextProps.text //true
prevProps.handleClick === nextProps.handleClick //true
prevProps.activeClass === nextProps.activeClass //true
handleClick is from an hook and I used useCallback to get always the same reference, I don't have other props so I don't know why
prevProps === nextProps
is still false. This happens in others child components, so I don't want to add a custom function in every one of them, what should I check next to ensure that prevProps === nextProps is true?
Upvotes: 1
Views: 7406
Reputation: 1
i would suggest to convert it into the JSON rather than checking for the reference (===). example :-
JSON.stringify(prevProps) === JSON.stringify(nextProps)
or
JSON.stringify(prevProps.itemType) === JSON.stringify(nextProps.itemType) ||
JSON.stringify(prevProps.text) === JSON.stringify(nextProps.text) ||
JSON.stringify(prevProps.handleClick) === JSON.stringify(nextProps.handleClick) ||
JSON.stringify(prevProps.activeClass) === JSON.stringify(nextProps.activeClass);
converting to JSON will check the data inside the props and will check if both strings are same or not.
Upvotes: 0
Reputation: 15478
This code:
}, (prevProps, nextProps) => {
prevProps === nextProps
};
is not quite right. It works if you leave out the {}. Otherwise, it should be
}, (prevProps, nextProps) => {
return prevProps === nextProps
};
Upvotes: 0
Reputation: 2324
use JSON.stringify(prevProps) === JSON.stringify(nextProps)
Upvotes: 0
Reputation: 518
If you use ===
JS will make a reference comparison and what you need is a deep comparison. For do this you could use something like this => https://stackoverflow.com/a/38416465/8548193
or use lodash [https://lodash.com/docs/] to make it more easier;
with lodash it will be something like this:
const _ = require("lodash");
_.isEqual(prevProps, nextProps);
Upvotes: 5