最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Specialized shouldComponentUpdate on PureComponent - Stack Overflow

programmeradmin2浏览0评论

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?

Share Improve this question asked Feb 14, 2018 at 16:48 corvidcorvid 11.2k12 gold badges70 silver badges134 bronze badges 1
  • 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
Add a comment  | 

4 Answers 4

Reset to default 9 +25

You 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

发布评论

评论列表(0)

  1. 暂无评论