She*_*ueh 16 javascript comparison equality reactjs react-redux
我正在研究React-Redux-v.7.1提供的 Hooks API 如何工作,并在平等比较和更新(https://react-redux.js.org/api/hooks#equality-comparisons-and-更新):
"从 v7.1.0-alpha.5 开始,默认比较是严格的===引用比较。这与connect()不同,后者使用对mapState调用结果的浅层相等性检查来确定是否需要重新渲染. 这对您应该如何使用useSelector()有几个影响。 ”
我想知道为什么严格相等比connect()使用的浅相等更好?然后我查看了他们的平等比较:
useSelector()的默认严格相等检查只是检查a===b
const refEquality = (a, b) => a === b
Run Code Online (Sandbox Code Playgroud)
并且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
}
Run Code Online (Sandbox Code Playgroud)
根据MDN 中 Object.is() 的描述: “ Object.is没有类型转换,也没有对 NaN、-0 和 +0 进行特殊处理(除了那些特殊的数值外,它的行为与 === 相同) ”
我不知道为什么a === b比一系列相等检查更好。(这是我第一次在这里提问,为粗鲁或缺乏信息而道歉)
azu*_*ndo 20
With connect, mapStateToProps returns a composite object of all of the state being selected from the store, so a shallow comparison across its keys makes sense. With useSelector, the pattern is often to only return a single value for each invocation of useSelector, similar to the way that the useState hook only handles a single value instead of all of the state values. So if each call to useSelector returns a value directly then a strict equality check makes sense vs a shallow comparison. A short example should make this more clear.
import {connect} from 'react-redux';
const mapStateToProps = state => (
{keyA: state.reducerA.keyA, keyB: state.reducerB.keyB}
);
export default connect(mapStateToProps)(MyComponent);
Run Code Online (Sandbox Code Playgroud)
Here mapStateToProps is called every time the store changes in any way, so the return value will always be a new object, even if keyA and keyB do not change. So a shallow comparison is used to decide if a re-render is needed.
For the hooks case:
import {useSelector} from 'react-redux';
function MyComponent(props) {
const keyA = useSelector(state => state.reducerA.keyA);
const keyB = useSelector(sate => state.reducerB.keyB);
...
}
Run Code Online (Sandbox Code Playgroud)
Now the result of the useSelector hooks are the individual values from the store, not a composite object. So using strict equality as the default here makes sense.
If you want to use only a single useSelector hook that returns a composite object, the docs you linked to have an example of using the shallowEqual equality function: https://react-redux.js.org/api/hooks#equality-comparisons-and-updates
| 归档时间: |
|
| 查看次数: |
5745 次 |
| 最近记录: |