I'm using React Native memo
to decide whether my component should re-render or not. My props need more than a shallow compare so I figured I can use Lodash
isEqual
. However, for some reason it returns false for identical objects. The issue is a prop userChildren
which is an array of objects. To get it to work I need to remap the whole array which I don't understand why that would be needed.
const areEqual = (
{ userChildren: prevChildren, ...prevProps },
{ userChildren: nextChildren, ...nextProps }
) => {
console.log(
_.isEqual(
prevChildren.map((p) => ({ ...p })),
nextChildren.map((p) => ({ ...p }))
)
); // Returns true
console.log(_.isEqual(prevChildren, nextChildren)); // Returns false
console.log(prevChildren);
console.log(nextChildren);
return (
_.isEqual(prevProps, nextProps) &&
_.isEqual(
prevChildren.map((p) => ({ ...p })),
nextChildren.map((p) => ({ ...p }))
)
);
};
export default memo(RootNavigator, areEqual);
The log output can be seen below:
LOG true
LOG false
LOG [{"birthDate": "2022-09-14", "firstName": null, "gender": null, "id": "189", "showGender": null, "userId": "XXX"}]
LOG [{"birthDate": "2022-09-14", "firstName": null, "gender": null, "id": "189", "showGender": null, "userId": "XXX"}]
EDIT
There seems to be something with nextProps
that breaks the isEqual:
console.log(
'nextChildren',
_.isEqual(
[
{
birthDate: '2022-09-14',
firstName: null,
gender: null,
id: '189',
showGender: null,
userId: 'XXX',
},
],
nextChildren
)
);
console.log(
'prevChildren',
_.isEqual(prevChildren, [
{
birthDate: '2022-09-14',
firstName: null,
gender: null,
id: '189',
showGender: null,
userId: 'XXX',
},
])
);
Gives the log output:
LOG nextChildren false
LOG prevChildren true
.isEqual()
compares objects by reference._.isEqual({"foo":"bar"}, {"foo":"bar"})
istrue