javascript - React-Redux 中的严格相等 (===) 与浅度相等检查

标签 javascript reactjs react-redux comparison equality

我正在研究 React-Redux-v.7.1 提供的 Hooks API 的工作原理,并在平等比较和更新 ( https://react-redux.js.org/api/hooks#equality-comparisons-and-updates ) 中看到它:

从 v7.1.0-alpha.5 开始,默认比较是严格的 === 引用比较。这与 connect() 不同,它对 mapState 调用的结果使用浅层相等性检查来确定是否需要重新渲染。这对您应该如何使用 useSelector() 有几个影响。

我想知道为什么严格相等比connect()使用的浅层相等更好?然后我研究了他们的平等比较:

默认严格相等检查useSelector()只是检查a===b

const refEquality = (a, b) => a === b

以及 react-redux/src/connect/connect.js 中的相等性检查正在使用 Object.is() 以及其他检查,与 react 中的相同.

// The polyfill of Object.is()
function is(x, y) {
  if (x === y) {
    return x !== 0 || y !== 0 || 1 / x === 1 / y
  } else {
    return x !== x && y !== y
  }
}

export default function shallowEqual(objA, objB) {
  if (is(objA, objB)) return true

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

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

  if (keysA.length !== keysB.length) return false

  for (let i = 0; i < keysA.length; i++) {
    if (!hasOwn.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) {
      return false
    }
  }

  return true
}

根据the description of Object.is() in MDN:Object.is 不进行类型转换,也不对 NaN、-0 和 +0 进行特殊处理(使其与 === 具有相同的行为,除了那些特殊的数值)。

我不知道为什么a === b比一系列相等检查更好。 (这是我第一次在这里提问,对于粗鲁或缺乏信息表示歉意)

最佳答案

使用 connect 时,mapStateToProps 返回从存储中选择的所有状态的复合对象,因此对其键进行浅层比较是有意义的。使用 useSelector 时,该模式通常只为每次调用 useSelector 返回一个值,类似于 useState 钩子(Hook)仅处理的方式单个值而不是所有状态值。因此,如果每次调用 useSelector 都直接返回一个值,那么严格的相等检查与浅层比较相比就有意义。一个简短的例子应该可以让这一点更加清楚。

import {connect} from 'react-redux';

const mapStateToProps = state => (
  {keyA: state.reducerA.keyA, keyB: state.reducerB.keyB}
);
export default connect(mapStateToProps)(MyComponent);

这里,每次存储以任何方式发生更改时都会调用 mapStateToProps,因此返回值将始终是一个新对象,即使 keyAkeyB 不要改变。因此,通过浅层比较来决定是否需要重新渲染。

对于钩子(Hook)案例:

import {useSelector} from 'react-redux';

function MyComponent(props) {
  const keyA = useSelector(state => state.reducerA.keyA);
  const keyB = useSelector(sate => state.reducerB.keyB);
  ...
}

现在,useSelector Hook 的结果是来自存储的各个值,而不是复合对象。因此,在这里使用严格相等作为默认值是有意义的。

如果您只想使用返回复合对象的单个 useSelector 钩子(Hook),您链接到的文档有一个使用 shallowEqual 相等函数的示例:https://react-redux.js.org/api/hooks#equality-comparisons-and-updates

关于javascript - React-Redux 中的严格相等 (===) 与浅度相等检查,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58212159/

相关文章:

JavaScript/DOM - "CSS Selector"和属性之间有区别吗?

javascript - 为什么我们在比较两个组件相等时需要 toJSON?

reactjs - 如何在 React Material UI 中为属性添加 css

javascript - 如何根据字符串值实例化对象

javascript - 在 Redux mapDispatchToProps 中使用组件状态或 props

javascript - 循环响应对象并使用 javascript/jquery 显示 id 和名称

javascript - getImageData 给出 "undefined is not a function"错误

javascript - 从 android MainActivity 访问 js 变量

reactjs - reducer 可以监听其他 Action 吗?

javascript - 有没有一种方法可以从 React Redux 中的一个操作调用另一个操作