Redux:部分重新渲染如何工作? [英] Redux: How do partial re-renderings work?

查看:42
本文介绍了Redux:部分重新渲染如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题是关于使用 React-Redux 进行部分重新渲染的内部结构.

为了解释我的意思,我将首先介绍一种非常粗糙的技术,用于在没有任何状态管理库的情况下管理状态.该技术使用了一个巨大的AppState"对象,该对象归顶级 App 组件所有.假设这个 AppState 不仅拥有状态属性,还拥有几个改变这些状态属性的回调.此外,假设我们使用 props 在整个组件层次结构中传递这个 AppState.多亏了 ES6-spread 语法,可以在没有大量样板代码的情况下传递大量道具.在顶级 App 组件中,它将如下所示:

在所有其他组件中,它将如下所示:

需要注意的是 ES6-spread 语法实际上并没有传递 AppState 对象.相反,它提取所有 AppState 属性并将它们作为单独的道具传递.

现在我们应该区分 AppState 的顶级属性和嵌套的子属性:

  • 如果我通过调用 setState 来改变这个 AppState 的顶级属性,那么整个应用将重新渲染(除非我使用纯组件之类的东西).
  • 但是,如果我更改此 AppState 的嵌套子属性,则不会发生任何事情,因为 React 不会注意到属性更改.

这引出了我的最后一个问题:

  • 与 Redux 相比,这种粗略的方法的渲染性能如何?
  • Redux 究竟是如何处理部分渲染"的,以至于只有一些组件在状态变化后重新渲染?

解决方案

如果我通过调用 setState 来改变这个 AppState 的顶级属性,那么整个应用程序将重新渲染(因为一切都取决于 AppState).

如果你改变并使用纯组件,那么什么都不会渲染,你通过创建一个新的状态对象来改变状态.

<块引用>

然而,如果我改变这个 AppState 的嵌套子属性,那么什么都不会发生,因为 React 没有注意到属性的变化.

这仅在您 mutate 并且组件是纯的情况下才成立.

<块引用>

与 Redux 相比,这种粗略的方法的渲染性能如何?

道具钻孔将重新渲染整个树,但使用未更改状态的分支如果它们是纯的,则不会重新渲染.道具钻取不利于维护,因为如果您需要重构大子状态逻辑,您可能需要重构整个树或分支.但是从性能的角度来看,如果您使用纯组件并且在传递回调时要小心而不是在每次渲染时重新创建它们,它就不会受到太大影响(请参阅 useCallback).

<块引用>

Redux 究竟是如何处理部分渲染"的,以至于只有一些组件在状态改变后重新渲染?

React-redux useSelector 或 connect mapStateToProps 总是在每次调度改变状态和渲染之前调用.

如果结果与上次不同,则 react-redux 将触发组件的渲染.如果组件获得了 props,那么也可能触发渲染,因为 props 发生变化并且 mapstate/selector 将被执行.

当 mapState 或 selector 的结果发生变化时,连接的组件将观察状态并渲染.此处

This question is about internals for partial re-renderings with React-Redux.

To explain what I mean, I will first introduce a very crude technique for managing state without any state management libary. The technique uses a a huge "AppState"-object that is owned by the top-level App-component. Suppose that this AppState holds not only state-properties, but also several callbacks that mutate those state-properties. Furthermore, suppose that we use props to pass down this AppState throughout the entire component hierarchy. Thanks to the ES6-spread syntax, passing a huge number of props can be done without a lot of boilerplate code. In the top-level App-component, it will look like this:

<ChildComponent {...this.state} />

In all other components, it will look like this:

<GrandChildComponent {...this.props} />

It is important to note that the ES6-spread syntax does not actually pass the AppState-object. Instead, it extracts all the AppState-properties and passes them as separate props.

Now we should distinguish between top-level properties and nested child-properties of the AppState:

  • If I mutate a top-level property of this AppState by calling setState, then the entire app will re-render (unless I use things like pure components).
  • However, if I change a nested child-property of this AppState, then nothing will happen because React does not notice the property change.

This leads to my final questions:

  • What is the render-performance of this crude approach in comparison to Redux?
  • How exactly does Redux handle "partial renderings", such that only some of the Components re-render after a state mutation?

解决方案

If I mutate a top-level property of this AppState by calling setState, then the entire app will re-render (because everything depends on the AppState).

If you mutate and use pure components then nothing will render, you change state by creating a new state object.

However, if I mutate a nested child-property of this AppState, then nothing will happen because React does not notice the property change.

This is only true if you mutate and components are pure.

What is the render-performance of this crude approach in comparison to Redux?

Prop drilling will re render the entire tree but branches that use state that didn't change won't re render if they are pure. Prop drilling is bad for maintenance because if you need to refactor grand child state logic you may need to refactor the whole tree or branch. But from a performance point it would not take a big hit provided that you use pure components and are careful when passing callbacks and not re creating them on every render (see useCallback).

How exactly does Redux handle "partial renderings", such that only some of the Components re-render after a state mutation?

React-redux useSelector or connect mapStateToProps are always called every time dispatch changed state and before rendering.

If the result is different than last result then react-redux will trigger render of the component. If the component gets props then a render could also be triggered because props change and mapstate/selector will be executed.

A connected component will observe state and render when the result of mapState or selector has changed. An example app with logs showing what react-redux will execute can be found here

这篇关于Redux:部分重新渲染如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆