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

2022-08-30 04:42:37

在 React 的这个文档中,据说

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

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

我们不应该改变国家。

如果我们没有改变状态,那么比较将始终返回false,因此应该Component更新将始终返回true。我对它是如何工作的以及我们将如何覆盖它以提高性能感到困惑。


答案 1

浅层比较确实检查了相等性。比较标量值(数字,字符串)时,它会比较它们的值。在比较对象时,它不会比较它们的属性 - 只比较它们的引用(例如,“它们指向同一个对象吗?”)。

让我们考虑以下形状的对象user

user = {
  name: "John",
  surname: "Doe"
}

示例 1:

const user = this.state.user;
user.name = "Jane";

console.log(user === this.state.user); // true

请注意,您更改了用户名。即使有此更改,对象也是相等的。引用完全相同。

示例 2:

const user = clone(this.state.user);
console.log(user === this.state.user); // false

现在,无需对对象属性进行任何更改,它们就完全不同了。通过克隆原始对象,可以创建具有不同参照的新副本。

克隆函数可能如下所示(ES6 语法)

const clone = obj => Object.assign({}, ...obj);

浅层比较是检测更改的有效方法。它希望您不要更改数据。


答案 2

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

// 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.

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

// 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

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

附加说明:

  1. 执行深度比较毫无意义,因为如果状态对象是深度嵌套的,则会显著影响性能。但是,如果它不是太嵌套,并且您仍然需要深入比较,请在 shouldComponentUpdate 中实现它并检查这是否足够。
  2. 您绝对可以直接改变状态对象,但组件的状态不会受到影响,因为它在 react 的 setState 方法流中实现了组件更新周期挂钩。如果直接更新状态对象以有意避免组件生命周期挂钩,则可能应该使用简单的变量或对象来存储数据,而不是状态对象。