【问题标题】:About useSelector equality check关于 useSelector 相等性检查
【发布时间】:2020-05-06 02:57:57
【问题描述】:

我有一个关于 redux useSelector 相等性检查的问题。

参考 React Redux Hook 文档 (https://react-redux.js.org/api/hooks#equality-comparisons-and-updates)

useSelector 会对返回值和前一个值做引用比较,如果结果看起来不同,则强制重新渲染

我有一个像这样的默认博客商店状态

searcherParam: {
  keyword: '',
  categories: [],
  tags: [],
},

在组件中,我使用 useSelector 来检索值

const searchParam = useSelector(state => state.Blog.searcherParam)

如果我调度一个动作来更新具有相同值的 searcherParam,组件将重新渲染,因为返回值是对象(浅比较)

所以我通过多次调用 useSelector 来检索值

const keyword = useSelector(state => state.Blog.searchrParam.keyword)
const categories = useSelector(state => state.Blog.searchrParam.categories)
const tags = useSelector(state => state.Blog.searchrParam.tags)

然后我发送一个操作以再次使用相同的值更新 searcherParam

组件不会重新渲染

我不明白的一点是为什么组件不重新渲染?

如果useSelector做引用比较,分类值(数组)不应该是同一个引用,分派后的标签也是一样

我有什么误解吗?谢谢


不重新渲染的原因是因为我通过useState保存了类别(来自redux store)。

并使用useState的值来调度,所以它是相同的参考......

这里是codeandbox,抱歉Q_Q愚蠢的问题

https://codesandbox.io/s/useselector-test-u6pvg

【问题讨论】:

    标签: reactjs redux react-redux react-hooks


    【解决方案1】:

    所以当你这样做时:

    const newKeyword = useSelector(state => state.Blog.searchrParam.keyword)
    const newCategories = useSelector(state => state.Blog.searchrParam.categories)
    const newTags = useSelector(state => state.Blog.searchrParam.tags)
    

    这只是意味着,您希望获得它们每个的最新值。

    它没有翻译成这个:

    searcherParam: {
      keyword: newKeyword,
      categories: newCategories,
      tags: newTags,
    },
    

    因为searcherParam 在调度操作时将始终是一个新的引用。

    如果您只想重新渲染,如果 3 个属性中的任何一个发生更改,那么您可以简单地获取 state.searcherParam 并调度并实现重新渲染。

    当您只想在 keyword 更改时重新渲染时,获取单个属性会有所帮助。当cateogoriestags 发生变化时,您不想重新渲染。

    请注意,在这种情况下,如果您只是获取 searcherParam,它不会关心 3 个属性中的哪一个已更改,您将获得重新渲染,因为它是一个新引用。

    这是文档中提到的。


    在 cmets 讨论后。

    做了一个简单的实现。检查下面

    【讨论】:

    • 我知道如果我只是获取 searcherParam,它会重新渲染,因为它是一个新的参考。
    • 我不能理解的一点是分类和标签也是新的参考,为什么组件在调度后不会重新渲染
    • @Anymore 因此,当您执行state.searcherParam 时,它不会寻找属性更改。它只会重新渲染。如果你已经完成了state.searcherParam.keyword,那么由于我们已经获取了单个字段值,它只会在关键字更改时重新渲染。
    • 如果你的意思是你说组件不会重新渲染的那部分答案,它会重新渲染,因为searcherParam 永远是一个新的参考,无论其属性如何。
    • 是的,我知道 state.searcherParam.keyword => 只在关键字更改时重新渲染,但是 state.searcherParam.categories 呢?根据我的理解,分类也是一个新的参考,为什么组件不会重新渲染?
    【解决方案2】:

    以上属性不用单独选择,都可以通过解构searchrParam对象获得:

    const { newKeyword, newCategories, newTags } = useSelector(
         state => state.Blog.searchrParam
    )
    

    【讨论】:

      【解决方案3】:

      由于您尝试向商店添加相同的值,并且您直接从商店 (state.Blog.searchParam) 引用,因此您下面的代码不会导致重新渲染。

      const searchParam = useSelector(state => state.Blog.searcherParam)
      

      为了让它重新渲染,你可以试试下面

      const searchParam = useSelector(state => ({keyword: state.keyword, categories: state.categories, tags: state.tags}))
      

      上面的代码总是会尝试重新渲染,因为返回的对象引用不会相同。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-12-07
        • 2015-08-09
        • 2012-06-23
        • 2015-11-23
        • 2016-03-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多