首页 > 解决方案 > 究竟 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>
    )
}

我的问题是第二个参数究竟是如何工作的?

标签: reactjsreduxreact-redux

解决方案


在您的示例中,它没有任何区别。

shallowEquals当您选择内容可能相似但引用不同的对象时才有意义。

看到这两个对象:

const a = { foo: "bar" }
const b = { foo: "bar" }

console.log( a === b ) // will log false
console.log( shallowEquals(a, b)) // will log true

虽然ab是两个具有相似形状和内容的对象,但它们不是同一个对象。现在在and和 之间shallowEquals进行===比较,因为两者都是具有相同内容的字符串,所以会是真的。a.foob.fooa.foo === b.foo

如果您在选择器中创建一个新对象,这确实会起作用,比如说

const result = useSelector((state) => {

  return { a: state.foo.bar, b: state.baz.boo }

})

这样做的结果将始终是一个新对象,因此默认情况下useSelector将始终假定它们是不同的,即使它们实际上state.foo.barstate.baz.boo没有改变。如果您使用 a shallowEqualuseSelector将查看对象的直接(仅 1 级深度)子属性并进行比较。然后它会注意到它们实际上是相等的而不是重新渲染。


推荐阅读