reactjs - 究竟 useselector 是如何工作的?
问题描述
根据文档
useSelector(selector: Function, equalityFn?: Function)
useSelector 接受两个参数,第二个是可选的,因为默认情况下它比较严格 === 引用相等检查,但不比较浅相等。
const state = useSelector(state => {
console.log("useSelector rerendering");
return state.counter
}, shallowEqual)
另一个是
const state = useSelector(state => {
console.log("useSelector rerendering");
return state.counter
})
在这两种情况下,当 redux 存储状态更改以及本地状态更改时,组件都会重新渲染(在 useSelector 中打印 console.log)
我真的不明白它是如何工作的
完整的源代码
import React, { useState } from 'react'
import { shallowEqual, useDispatch, useSelector } from 'react-redux'
import { decrement, increment } from './store/actions'
export default function CounterHooks(props) {
const [submit, setSubmit] = useState(false)
const state = useSelector(state => {
console.log("useSelector rerendering");
return state.counter
}, shallowEqual)
const dispatch = useDispatch()
console.log("component rerendering");
const increments = () => {
dispatch(increment());
}
const decrements = () => {
dispatch(decrement());
}
const submitButton = () => {
console.log("component submit", submit);
setSubmit((previousState) => !previousState)
}
return (
<div>
<button onClick={increments} >Incrmeent Counter</button>
<br />
<button onClick={decrements} >Decrement Counter</button>
<br />
<button onClick={submitButton} >Submit</button>
<br />
<h2>total : {state.count}</h2> <br />
<h2>Submit:{String(submit)}</h2> <br />
</div>
)
}
我的问题是第二个参数究竟是如何工作的?
解决方案
在您的示例中,它没有任何区别。
shallowEquals
当您选择内容可能相似但引用不同的对象时才有意义。
看到这两个对象:
const a = { foo: "bar" }
const b = { foo: "bar" }
console.log( a === b ) // will log false
console.log( shallowEquals(a, b)) // will log true
虽然a
和b
是两个具有相似形状和内容的对象,但它们不是同一个对象。现在在and和 之间shallowEquals
进行===
比较,因为两者都是具有相同内容的字符串,所以会是真的。a.foo
b.foo
a.foo === b.foo
如果您在选择器中创建一个新对象,这确实会起作用,比如说
const result = useSelector((state) => {
return { a: state.foo.bar, b: state.baz.boo }
})
这样做的结果将始终是一个新对象,因此默认情况下useSelector
将始终假定它们是不同的,即使它们实际上state.foo.bar
并state.baz.boo
没有改变。如果您使用 a shallowEqual
,useSelector
将查看对象的直接(仅 1 级深度)子属性并进行比较。然后它会注意到它们实际上是相等的而不是重新渲染。
推荐阅读
- elasticsearch - 弹性搜索中的模糊性
- oracle - Oracle docker 容器在 Mac M1 BigSur 上无法正常工作
- sql - 清理 SQL 上的数据 - 字符串
- 3dsmax - getInheritanceFlags 无法正常工作
- go - 关于在 Go 中混合数字类型的操作的问题
- typescript - 解析 webpack.config.ts 中的别名
- xcode - 如何解释/导出大型 plist 数据
- python - 如何使用 python 和 django 使某些字段在 api 输出中不可见?
- flutter - 在 Flutter 中更改对话框的内容
- sql - 删除同一表SQL中不同类别中的重复值但保留第一个类别值