【问题标题】:How to efficiently design components / configure store when using react-redux使用 react-redux 时如何高效设计组件/配置 store
【发布时间】:2020-02-14 10:30:02
【问题描述】:

如果我有这样的组件树,

//App.js
const App = () => (
      <React.Fragment>
        <A />
        <B />
        <C />
      </React.Fragment>
    )

//A.js
const A = () => (
      <React.Fragment>
        <ChildA />
      </React.Fragment>
)

现在,假设所有三个组件 ABC 都使用 connect() 连接到存储。 问题是如果我用仅与组件A 相关的数据更新存储,那么BC 也将被重新渲染。一种可能的解决方案是配置options 参数以避免docs 中提到的重新渲染。

为每个互斥的组件创建多个 reducer 函数可以解决这个问题吗?如果是,如何以及如果否,那么可以做些什么来尽量减少不必要的重新渲染。

更新: 除了@tmdesign 的答案,如果我创建A 的子组件,那么childA 中的一些更新会导致AchildA 重新渲染,childA 重新渲染两次,因为两者都是连接普通reducer函数。

看,@tmdesign 的沙盒link

【问题讨论】:

    标签: reactjs redux react-redux


    【解决方案1】:

    我对您的问题很感兴趣,并检查了几次,希望有人能回答,我可以更深入地了解它是如何工作的。但这并没有发生,所以我做了一些调查并设置了一个代码沙箱来准确说明您的要求。

    https://codesandbox.io/s/spring-thunder-xbj5z

    在那里你会发现一个简单的 React + Redux 应用程序,它包含 3 个组件(A、B 和 C),每个组件依赖于不同的 reducer(reducerA、reducerB 和 reducerC),并且能够触发更新其 reducer 的操作(actionA 、actionB 和 actionC)。

    您会在每个组件的渲染方法中看到console.log 语句,明确说明每个组件何时重新渲染。

    试一试,您会发现组件已经仅在它们关心的 redux 状态更新时才智能地重新渲染——而不是在商店的任何部分更新时.

    换句话说,它实际上并不像您建议的那样工作(“如果我使用仅与组件 A 相关的数据更新存储,那么 B、C 也将被重新渲染。”)。当然,这些其他组件可以通过多种方式重新渲染,但在这里最基本的示例中,它们不会。

    很酷吧?

    【讨论】:

    • 我相信我们在连接组件到redux store时需要非常小心,至少我们应该只连接顶级组件到only store,并将数据作为props传递给他们的子组件。这将至少限制子组件的额外渲染。
    • 这是一个有趣的问题。 redux 的一大好处是您可以在任何地方访问商店,而无需像您所说的那样进行属性链接。但是,您至少部分正确。我已经使用子组件更新了示例。有趣的是,当孩子触发更新时,您确实会获得双重重新渲染,但当父母触发更新时则不会。我不确定是什么导致了这里的第一次重新渲染,但无论如何它不是 redux 存储更新(该值仍然是较早的值)。
    • 每当 A 的子组件触发 update 时,reducerA 就会更新状态,导致 A 的重新渲染,这也包括 A 的子组件的重新渲染,同样由于 child也连接到存储,会发生额外的重新渲染。虽然,它提出了更多的问题,但这似乎是一个可能的原因。
    • 但是,为什么不点击 A 上的按钮会导致相同的 2 重新渲染?一个用于redux->子更新,一个用于redux->父更新->子更新?
    • 实际上,它并没有因为商店更新而重新渲染,就像我在几个 cmets 之前建议的那样。这是一个不再需要的剩余 setState 调用,导致子组件重新渲染了额外的时间(感谢我的同事指出这一点。)
    【解决方案2】:

    在我看来,每个组件都需要有自己的功能,这对于防止出现您所说的情况很重要。例如,组件 A 呈现一个需要拥有自己的 reducer 和操作的人员列表。例如:

    人物状态

    persons: {
      data: [...]
      loading: false
      error: null
    }
    

    人员操作 PERSONS_FETCH_INITPERSONS_FETCH_SUCCESSPERSONS_FETCH_FAIL

    另外你还需要使用 react memo,如果组件 A 的订阅状态更新组件 A 将触发组件 App 的重新渲染,然后所有子组件(如 B、C 等)将重新渲染.

    【讨论】:

    • 您似乎建议为应用程序中的每个主要组件创建一个 reducer。但我仍然不相信为每个 reducer 函数创建三个动作的想法。
    • 不完全是,商店的每个状态都有一个动作和一个减速器,比如:用户、身份验证等。如果你给我你的应用程序的概述,我可以帮助你为商店建模! :)
    猜你喜欢
    • 2019-08-10
    • 2020-08-10
    • 2018-11-17
    • 2021-06-19
    • 2021-04-15
    • 2019-04-02
    • 2019-12-26
    • 2019-12-19
    • 2017-12-17
    相关资源
    最近更新 更多