深度比较反应中的对象道具无法正常工作



我正在通过减少不必要的重新租用器来优化React应用程序的性能。我正在使用的组件会收到一个包含一个包含许多键的对象,包括许多对象。我正在使用 shouldComponentUpdate检查道具的更改,但它无法正常工作:

shouldComponentUpdate(nextProps) {
    if (!(_.isEqual(nextProps, this.props))) {
        console.log('difference', _.differenceWith(nextProps, this.props));
        return true;
    }
  return false;
}

isEqual是lodash的一种方法,用于深度比较对象。differenceWith是一种用于在两个对象中找到差异的Lodash方法。奇怪的是,使用isEqual不会减少重新渲染,而differenceWith则打印一个空数组[]。但是,如果我使用JSON.stringify代替isEqual,则将重新租用者减少一半,但differenceWith仍打印[]

shouldComponentUpdate(nextProps) {
    if ( JSON.stringify(nextProps) !== JSON.stringify(this.props) ) {
        console.log('difference', _.differenceWith(nextProps, this.props));
        return true;
    }
  return false;
}

为什么isEqualJSON.stringify的行为实际上在做同样的事情时会有差异(请注意,isEqual也是订单敏感的(?

避免重新渲染的最佳方法是什么?

1-为什么在iSequal和json的行为上存在差异。

看看我在这里发现的东西。

很好。对于json.stringify((,订单很重要。因此,如果在两个对象中对键值对的排序有所不同,但是相同,则将返回false。尽管在lodash iSequal中并不重要,但它会像钥匙值对一样返回true。

const one = {
  fruit: '🥝',
  energy: '255kJ',
};
const two = {
  energy: '255kJ',
  fruit: '🥝',
};

// Using JavaScript
JSON.stringify(one) === JSON.stringify(two); // false
// Using Lodash
_.isEqual(one, two); // true

这意味着您可以使用JSON.stringify,但在所有情况下都不能工作,因此您不应该将其用于情况。

我还找到了一个比较两者的基准。JSON.stringify对于较不深嵌套的对象更好,但是_.isEqual使用更深的嵌套对象变得更好。

_。差异Wich的差距接收3个参数,2个是要比较的数组,第三个是比较器。

这样做_.differenceWith(nextProps, this.props)与您在文档中看到的_.difference(nextProps, this.props)相同

_。

此方法类似于_.Difference,除非它接受比较器,该比较器被调用以将数组的元素与值进行比较。结果值的顺序和参考由第一个数组确定。比较器用两个参数调用:( arrval,othval(。

_。差

使用SameValuezero中的其他给定数组中未包含的数组值数组来进行平等比较。结果值的顺序和参考由第一个数组确定。

因此,使用其中之一将返回一个具有不同值的新数组。如果返回[],则表示数组具有相同的值,但可以在其他其他中。

_.differenceWith如果您有一系列对象,并且还想比较对象。这可以在Doc的示例中看到。

var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
_.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);
// => [{ 'x': 2, 'y': 1 }]

2-避免重新渲染的最佳方法是什么?

对于您的情况,我建议使用 _.isEqual,因为它可以准确比较数组的顺序,并且您可以具有具有相同属性但不同订单的对象,并且会相同。


使用说

很奇怪的是,使用iSqual不会减少重新渲染,并且在差异上打印一个空数组[]。但是,如果我使用json.stringify而不是iSequal,则将重新租赁减少一半...

我不确定为什么会发生这种情况,它会对很多事情进行贬低,但是如果您想比较组件的状态或道具,绝对应该使用_.isEqual

您也可以React.memoReact.PureComponent,这在某些情况下可能会有所帮助。

您可以在memo

的文档中看到

如果您的功能组件在相同的道具下呈现相同的结果,则可以将其包装在呼叫中。这意味着React会跳过渲染组件,并重用最后的渲染结果。 ... 此方法仅作为性能优化存在。不要依靠它来"防止"渲染,因为这可能会导致错误

PureComponent的文档

react.purecomponent类似于react.component。它们之间的区别在于react.component并未实现showscomponentupdate((,而是react.purecomponent通过浅道具和状态比较实现它。

如果您的React组件的Render((函数在相同的道具和状态下呈现相同的结果,则可以使用React.purecomponent。在某些情况下为性能提升。

最新更新