React渲染状态
React渲染
Context API
React的Context API提供了一种在组件树中传递数据的方式,而不使用props
,但不应用于状态管理,因为它需要手动更新。在上下文的Provider
中的任何组件都可以使用Consumer
组件或仅适用于函数组件的useContext()
钩子来访问上下文实例中的数据。
当将新引用传递给上下文的Provider
时,它将导致任何连接的组件更新。React将在组件树中查找任何消费上下文的组件,并更新它们以反映上下文值的变化。将新对象传递给上下文的Provider
实际上是一个新引用,因为上下文保存一个值(在本例中是一个对象)。
上下文优化
默认情况下,父组件对上下文Provider
的渲染的任何更新都会导致所有子组件重新渲染,而不管上下文中的更改,这是由于React的渲染过程。为了避免在父组件更改时重新渲染子组件,可以使用记忆化,这将导致React跳过被跳过组件的整个子树。
当上下文更新时,React还会检查子树中消费上下文的组件。这允许在不重新渲染的记忆化父组件下消费上下文的组件使用更新后的上下文并根据需要进行渲染。在上下文消费组件重新渲染之后,React将继续递归地渲染其子组件,就像通常一样。
通常,最好将上下文Provider
下的组件进行记忆化。这样,父组件的更新将不会导致整个子树重新渲染,而只会重新渲染消费上下文的组件。
React-Redux
React-Redux为JavaScript应用程序提供了与Redux的绑定,Redux是一个状态容器,并且与React的Context API有一些不同。其中一个关键区别是,React-Redux只重新渲染需要渲染的组件,因为订阅Redux存储的组件读取最新的存储状态,对值进行差异比较,并仅在相关数据发生更改时强制重新渲染,而React在订阅回调过程中根本不参与。
虽然这很可能意味着与使用上下文相比,较少的组件需要重新渲染,但是当存储状态更新时,React-Redux始终对树中的每个连接组件执行其mapStateToProps
和useSelector
函数。这些计算通常比React的渲染更廉价,但是如果执行了昂贵的计算或者在不应该返回新引用时返回了新引用,可能会出现问题。
React-Redux优化
React-Redux提供了两种连接到其存储的方法,执行必要的工作并返回组合的props
:
connect
(任何组件):高阶组件(HOC),用于包装任何给定的组件useSelector
(函数组件):在函数组件内部调用的钩子
connect
的行为很像记忆化React组件(即使用React.PureComponent
或React.memo()
),仅在组合的props
发生更改时更新包装的组件。这意味着从父组件或传递的函数传递新引用仍然会导致重新渲染。使用connect
包装的组件通常从存储状态中读取较小的数据片段,由于这个原因重新渲染的可能性较小,并且通常会影响其树下的较少组件。
另一方面,useSelector
无法阻止在其父组件渲染时重新渲染组件。当仅使用useSelector
时,由于没有其他使用connect
的组件来阻止它们重新渲染,组件树的较大部分将由于Redux存储更新而重新渲染。您可以根据需要使用React.memo()
来优化此行为,以防止不必要的重新渲染。