I might be missing something, but I have a component like this
export default MyComponent extends React.PureComponent {
// ...
}
When MyComponent is part of another components render method, MyComponent re-renders every time the parent renders, even when the props/state are unchanged. So it seems changing from React.Component
to React.PureComponent
did not make the component "pure".
I tried adding
console.info(this.shouldComponentUpdate)
inside the one of the components methods, and it says it is undefined. Isn't React.PureComponent
supposed to add a shallow-comparing shouldComponentUpdate
method?
This has now happened with React 15.5.4 and 15.6.0
A PureComponent doesn't declare the shouldComponentUpdate
directly. You can't visit it with this.shouldComponentUpdate
. In the React source code there is a shouldUpdate
variable:
(the source code below is simplified)
// default is true
var shouldUpdate = true;
if (inst.shouldComponentUpdate) {
shouldUpdate = inst.shouldComponentUpdate(
nextProps,
nextState,
nextContext,
);
} else {
// if it's a PureComponent
if (this._compositeType === ReactCompositeComponentTypes.PureClass) {
shouldUpdate =
!shallowEqual(prevProps, nextProps) ||
!shallowEqual(inst.state, nextState);
}
}
// ...
if (shouldUpdate) {
// re-render ..
}
Since it's just shallow equal, the code bellow returns false and you get a re-render:
const propA = { foo: 'bar' }
const nextPropA = { foo: 'bar' }
shallowEqual(propA, nextPropA) // false
So use objects and arrays carefully. To prove that PureComponent works, see this example (v15.6): https://codepen.io/CodinCat/pen/eRdzXM?editors=1010
Clicking the button won't trigger Foo
's render:
Here is another example that PureComponent may not work for you: https://codepen.io/CodinCat/pen/QgKKLg?editors=1010
The only difference is <Foo someProp={{ foo: 'bar' }} />
Because { foo: 'bar' } !== { foo: 'bar' }
, React will re-render every single time. So writing inline objects and arrays in props directly is not a good practice. A common mistake is writing inline style:
<Foo style={{ color: 'pink' }} />
In this case Foo
will always re-render even if it's a PureComponent. If you are facing this problem you can simply extract and store the object somewhere, for example:
const someProp = { foo: 'bar' }
<Foo someProp={someProp} />
Since someProp === someProp
, the PureComponent works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With