Reputation: 8136
I'm having some trouble using React PureComponent
s with Immutable.js. Consider the following demo:
https://codepen.io/SandoCalrissian/pen/QaEmeX
In it 2 components are rendered. The first (NoramlPure
) is a normal PureComponent
while the second (ImmutablePure
) is a normal Component
with a custom shouldComponentUpdate
that checks props for an equals
method. Both take a single Immutable Map
as a prop which is re-formed on every render cycle. Both also print a message to the console every time they re-render.
I then trigger two render cycles.
I'm expecting both to only render once. However, the console shows the following:
rendering
rendering normal pure component
rendering immutable pure component
rendering
rendering normal pure component
My custom component works as expected, but the built in PureComponent
renders both times (despite getting the same data).
Seeing as React links to Immutable.js in the documentation for PureComponent
(and since they're both made by Facebook) I'd sort of expect the two to work together naturally, but as far as I can tell PureComponent
s don't ever call any Immutable.js equality checkers.
Is there any way to make PureComponent
s work with Immutable.js objects?
Or am I stuck using my PureImmutable
component as a base-class across my entire project?
Upvotes: 3
Views: 1505
Reputation: 12305
Currently you can use this ImmutablePureComponent
implementation instead of the standard PureComponent
:
https://www.npmjs.com/package/react-immutable-pure-component
Upvotes: 0
Reputation: 2465
Hi Sandy the problem is that in each render you are recreating the map prop and React.PureComponent is basically checking props.map === nextProps.map. They are different so it re-render.
Check this one:
class NormalPure extends React.PureComponent<any, any> {
public render() {
console.log("\trendering normal pure component");
return <div />;
}
}
class ImmutablePure extends React.Component<any, any> {
public shouldComponentUpdate(nextProps) {
return !Object.keys(this.props).every((key) => {
const val = this.props[key];
const nextVal = nextProps[key];
if (typeof val.equals === "function") {
return val.equals(nextVal);
} else {
return val === nextVal;
}
});
}
public render() {
console.log("\trendering immutable pure component");
return <div />;
}
}
const wrapper = document.getElementById("wrapper");
const obj = {
"a": 1,
"b": 2,
"c": 3,
};
const immutableMap = Immutable.fromJS(obj);
function render() {
console.log("rendering");
ReactDOM.render(
<div>
<NormalPure map={immutableMap} />
<ImmutablePure map={Immutable.fromJS(obj)} />
</div>,
wrapper
);
}
render();
render();
Is there any way to make PureComponents work with Immutable.js objects? No. PureComponent use a strict equality comparison (===). It dosen't know about Immutablejs
Or am I stuck using my PureImmutable component as a base-class across my entire project? Yes, if you want to check Immutablejs objects with the equals method.
Upvotes: 3