浅表比较如何在反应中起作用

JavaScript

TomMandy

2020-03-13

React 文档中,据说

shallowCompare对当前props和nextProps对象以及当前状态和nextState对象执行浅层相等性检查。

我无法理解的是,如果它浅浅地比较对象,则shouldComponentUpdate方法将始终返回true,因为

我们不应该改变国家。

如果我们不改变状态,则比较将始终返回false,因此shouldComponent更新将始终返回true。我对它的工作方式以及如何将其覆盖以提高性能感到困惑。

第1390篇《浅表比较如何在反应中起作用》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

4个回答
路易Stafan 2020.03.13

浅比较通过检查基本值(例如字符串,数字)和对象的情况下两个值是否相等来进行工作,它仅检查引用因此,如果浅比较深层嵌套的对象,它将只检查引用而不是该对象内部的值。

蛋蛋Near 2020.03.13

在React中有浅比较的遗留解释

shallowCompare对当前props和nextProps对象以及当前状态和nextState对象执行浅层相等性检查。

它通过迭代要比较的对象的键并在每个对象中的键的值不严格相等时返回true来实现此目的。

UPD当前文档说明了浅比较:

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

React.PureComponent的shouldComponentUpdate()仅对对象进行浅比较。如果这些数据包含复杂的数据结构,则可能会产生假阴性,从而产生更大的差异。仅在期望具有简单的道具和状态时才扩展PureComponent,或者在知道深度数据结构已更改时才使用forceUpdate()

UPD2:我认为和解也是浅层比较理解的重要主题。

猿小小 2020.03.13

如果没有键,上述@supi(https://stackoverflow.com/a/51343585/800608的浅相等片段将失败这是一个应该考虑到的实现:prevObjnewObj

const shallowEqual = (objA, objB) => {
  if (!objA || !objB) {
    return objA === objB
  }
  return !Boolean(
    Object
      .keys(Object.assign({}, objA, objB))
      .find((key) => objA[key] !== objB[key])
  )
}

请注意,如果没有Polyfill,以上内容在Explorer中将不起作用。

梅Harry 2020.03.13

浅表比较是指使用“ ===“或严格相等性完成比较对象的属性,并且不会对属性进行更深层的比较。例如

// a simple implementation of the shallowCompare.
// only compares the first level properties and hence shallow.
// state updates(theoretically) if this function returns true.
function shallowCompare(newObj, prevObj){
    for (key in newObj){
        if(newObj[key] !== prevObj[key]) return true;
    }
    return false;
}
// 
var game_item = {
    game: "football",
    first_world_cup: "1930",
    teams: {
         North_America: 1,
         South_America: 4,
         Europe: 8 
    }
}
// Case 1:
// if this be the object passed to setState
var updated_game_item1 = {
    game: "football",
    first_world_cup: "1930",
    teams: {
         North_America: 1,
         South_America: 4,
         Europe: 8 
    }
}
shallowCompare(updated_game_item1, game_item); // true - meaning the state
                                               // will update.

尽管两个对象看起来都相同,game_item.teams但是与的引用不同updated_game_item.teams对于2个相同的对象,它们应指向相同的对象。因此,这导致状态被评估为要更新

// Case 2:
// if this be the object passed to setState
var updated_game_item2 = {
    game: "football",
    first_world_cup: "1930",
    teams: game_item.teams
}
shallowCompare(updated_game_item2, game_item); // false - meaning the state
                                               // will not update.

这次,为了严格比较,每个属性都返回true,因为新对象和旧对象中的teams属性都指向同一个对象。

// Case 3:
// if this be the object passed to setState
var updated_game_item3 = {
    first_world_cup: 1930
}
shallowCompare(updated_game_item3, game_item); // true - will update

updated_game_item3.first_world_cup属性未通过严格评估,因为1930是数字而game_item.first_world_cup字符串是。如果比较宽松(==),这将过去。尽管如此,这也会导致状态更新。

补充说明:

  1. Doing deep compare is pointless as it would significantly effect performance if the state object is deeply nested. But if its not too nested and you still need a deep compare, implement it in shouldComponentUpdate and check if that suffices.
  2. You can definitely mutate the state object directly but the state of the components would not be affected, since its in the setState method flow that react implements the component update cycle hooks. If you update the state object directly to deliberately avoid the component life-cycle hooks, then probably you should be using a simple variable or object to store the data and not the state object.

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android