redux useselector的工作原理是什么?

q5lcpyga  于 2022-11-24  发布在  其他
关注(0)|答案(2)|浏览(179)

根据文件

useSelector(selector: Function, equalityFn?: Function)

useSelector接受两个参数,第二个参数是可选的,因为默认情况下它比较strict ===引用相等性检查,而不是shallow相等性检查。

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>
    )
}

我的问题是第二个参数到底是如何工作的?

frebpwbc

frebpwbc1#

在您的示例中,这并没有什么区别。
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是两个具有相似形状和内容的对象,但它们不是同一个对象。现在shallowEqualsa.foob.foo之间进行===比较,由于两者都是具有相同内容的字符串,因此a.foo === b.foo将为真。
如果您在选择器中创建一个新对象,例如

const result = useSelector((state) => {

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

})

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

f5emj3cl

f5emj3cl2#

考虑以下为减速器,

const userSlice = (
{name: "user", initialState: {name: "test", isLoggedIn: true}, 
reducers: {updateUser(state, action) => (state.isLoggedIn=action.payload["isLoggedIn"])}
}

如果我们用如下所示的相同数据向reducer发送一个动作,

const result = useSelector(state => state.users)
dispatch({isLoggedIn: true})

上面的代码不会导致组件重新呈现,因为我们引用的state.users与前一个相同。
我们可以通过以下更改使其重新渲染,

const result = useSelector(state => ({name: state.users.name, isLoggedIn: state.users.isLoggedIn)
dispatch({isLoggedIn: true})

在上面的代码中,我们直接返回了一个对象,因此无论何时运行useSelector,由于引用相等,返回的对象都不会相同。

相关问题