I am trying to create a component that shouldn't when a certain property is true, but should perform a shallow compare (the default for PureComponent
).
I've tried doing the following behavior:
export default class ContentsListView extends PureComponent<Props> {
shouldComponentUpdate(props: Props) {
if (props.selecting) {
return false;
}
return super.shouldComponentUpdate(props);
}
render() {
}
}
However, super.shouldComponentUpdate
is not defined. Is there some way to "tap into" the shallow compare of PureComponent
without writing my own?
I am trying to create a component that shouldn't when a certain property is true, but should perform a shallow compare (the default for PureComponent
).
I've tried doing the following behavior:
export default class ContentsListView extends PureComponent<Props> {
shouldComponentUpdate(props: Props) {
if (props.selecting) {
return false;
}
return super.shouldComponentUpdate(props);
}
render() {
}
}
However, super.shouldComponentUpdate
is not defined. Is there some way to "tap into" the shallow compare of PureComponent
without writing my own?
- 2 did you ever find a way to do this, I too would like the default behaviour of a PureComponent, with one additional check on a particular prop? – andy mccullough Commented Jan 15, 2019 at 11:14
4 Answers
Reset to default 9 +25You should not implement shouldComponentUpdate
when you are extending your component using PureComponent
. If however you want to use the shouldComponentUpdate functionality you can simply write a wrapper component around your original component or use HOC to implement your custom shouldComponentUpdate
and render the PureComponent
Sample code
class ContentsListView extends PureComponent {
render() {
console.log("render list");
return (
...
);
}
}
export default class Wrapper extends React.Component {
shouldComponentUpdate(props) {
if (props.selecting) {
return false;
}
return true;
}
render() {
return <ContentsListView {...this.props} />;
}
}
You can see a working demo on codesandbox here
There is no super.shouldComponentUpdate
in PureComponent
because it implements shallow checks by checking isPureReactComponent
property, not with shouldComponentUpdate
. A warning is issued when both isPureReactComponent
and shouldComponentUpdate
are in use because shouldComponentUpdate
efficiently overrides the behaviour of isPureReactComponent
.
React doesn't expose its shallowEqual
implementation, third-party implementation should be used.
In case this becomes a common task, own PureComponent
implementation can be used for extension:
import shallowequal from 'shallowequal';
class MyPureComponent extends Component {
shouldComponentUpdate(props, state) {
if (arguments.length < 2)
throw new Error('Do not mess super arguments up');
return !shallowequal(props, this.props) || !shallowequal(state, this.state);
}
}
class Foo extends MyPureComponent {
shouldComponentUpdate(props, state) {
if (props.selecting) {
return false;
}
return super.shouldComponentUpdate(props, state);
}
}
If you can consider writing your component in a function instead of class, try React.memo
.
React.memo is a higher order component. It’s similar to React.PureComponent but for function components instead of classes.
If your function component renders the same result given the same props, you can wrap it in a call to React.memo for a performance boost in some cases by memoizing the result. This means that React will skip rendering the component, and reuse the last rendered result.
By default it will only shallowly compare complex objects in the props object. If you want control over the comparison, you can also provide a custom comparison function as the second argument.
As a second argument, you can pass a function, where you can use prevProps, nextProps
, and return false, if you want it to render, or return true if you don't.
import React, { memo } from "react";
const ContentsListView = ({ selecting }) => {
return <div />;
};
const shouldComponentUpdate = (prevProps, nextProps) => {
if (nextProps.selecting) { return true; }
return JSON.stringify(prevProps) === JSON.stringify(nextProps)
}
const Component = memo(ContentsListView, shouldComponentUpdate);
I was looking for the same thing as you can see from my comment in January, I had eventually settled on using the shallow-compare
library - https://www.npmjs.com/package/shallow-compare
export default class ContentsListView extends Component<Props> {
shouldComponentUpdate(nextProps, nextState) {
if (props.selecting) {
return false;
}
return shallowCompare(this, nextProps, nextState);
}
render() {
}
}
however extend from Component, not PureComponent