简体   繁体   中英

React Native Redux: what's the best way to compare prevProps and this.props?

In my React Native app I want to trigger a function if a certain prop has changed. Something like this:

componentDidUpdate(prevProps) {
  if (prevProps.a !== this.props.a) {
    <trigger event>
  }
}

The problem is that I assume prevProps.a.== this.props.a will always be true because it's comparing by reference.

What's the best way to approach this, so that my event will be triggered only if a property of this.props.a has changed?

It's better to compare the properties directly instead of comparing the whole objects like this:

componentDidUpdate(prevProps) {
  if (prevProps.a.field1 === this.props.a.field1) {
    // Do stuff here
  }
}

However, if you still want to compare two objects with deeply nested properties, a simple way to do this is to stringify both objects, and then directly compare the strings:

if (JSON.stringify(prevProps.a) === JSON.stringify(this.props.a) {
    // Do stuff here
  }

It depends somewhat on the nature of the object a being compared. If it's a matter of specific properties, then you can obviously compare them individually and that is always going to be the most efficient approach. However, if you want to trigger the code on any change to a , including deep changes inside nested objects, then comparing the stringified representations of the objects (JSON.stringify) can do the trick. However it is also inefficient. An intermediate approach is to do a shallow compare, and here is some code (from the React team no less) to do that:

export function shallowEqual(objA: any, objB: any, compare?, compareContext?) {
  let ret = compare ? compare.call(compareContext, objA, objB) : void 0;

  if (ret !== void 0) {
    return !!ret;
  }

  if (objA === objB) {
    return true;
  }

  if (typeof objA !== 'object' || !objA || typeof objB !== 'object' || !objB) {
    return false;
  }

  const keysA = Object.keys(objA);
  const keysB = Object.keys(objB);

  if (keysA.length !== keysB.length) {
    return false;
  }

  const bHasOwnProperty = Object.prototype.hasOwnProperty.bind(objB);

  // Test for A's keys different from B.
  for (let idx = 0; idx < keysA.length; idx++) {
    const key = keysA[idx];

    if (!bHasOwnProperty(key)) {
      return false;
    }

    const valueA = objA[key];
    const valueB = objB[key];

    ret = compare ? compare.call(compareContext, valueA, valueB, key) : void 0;

    if (ret === false || (ret === void 0 && valueA !== valueB)) {
      return false;
    }
  }

If you need to do an efficient deep compare (more so than JSON.stringify), then using a library such as react-fast-compare ( here ) is your best bet.

(Note also that JSON.stringify is not perfect for some cases, since some objects like dates and functions are not stringified properly or at all. In practice those limitations usually aren't an issue in React, but you should be aware of them at least.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM