React.PureComponent doesn't execute shouldComponentUpdate
I may have missed something, but I have a component like this
export default MyComponent extends React.PureComponent {
// ...
}
When MyComponent is part of another component renderer, MyComponent re-renders every time the parent renders, even when props / state does not change. Thus, it seems that going from React.Component
to React.PureComponent
did not make the component "clean".
I tried adding
console.info(this.shouldComponentUpdate)
inside one of the component's methods and it says it's undefined. React.PureComponent
Should n't I add an shouldComponentUpdate
incomplete comparison method?
This has now happened with React 15.5.4 and 15.6.0
source to share
A PureComponent doesn't declare shouldComponentUpdate
directly. You cannot visit it with this.shouldComponentUpdate
. There is a variable in the React source code shouldUpdate
:
(simplified source code)
// default is true
var shouldUpdate = true;
if (inst.shouldComponentUpdate) {
shouldUpdate = inst.shouldComponentUpdate(
nextProps,
nextState,
nextContext,
);
} else {
// if it a PureComponent
if (this._compositeType === ReactCompositeComponentTypes.PureClass) {
shouldUpdate =
!shallowEqual(prevProps, nextProps) ||
!shallowEqual(inst.state, nextState);
}
}
// ...
if (shouldUpdate) {
// re-render ..
}
Since it's just shallow, the code below returns false and you get re-rendered:
const propA = { foo: 'bar' }
const nextPropA = { foo: 'bar' }
shallowEqual(propA, nextPropA) // false
So use objects and arrays carefully. To prove PureComponent works see this example (v15.6): https://codepen.io/CodinCat/pen/eRdzXM?editors=1010
Clicking the button doesn't trigger Foo
render:
Here's another example that PureComponent might 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 redraw every time. Therefore, it is not good practice to directly create inline objects and arrays in props. A common mistake is writing inline style:
<Foo style={{ color: 'pink' }} />
In this case, Foo
it will always re-render, even if it is PureComponent. If you encounter this problem, you can simply retrieve and store the object somewhere, for example:
const someProp = { foo: 'bar' }
<Foo someProp={someProp} />
Since someProp === someProp
PureComponent works.
source to share