如何限制 react-redux 连接更新重新渲染到特定的状态分支?

IT技术 javascript reactjs redux react-redux rendering
2021-04-03 21:04:36

我有一个更新全局计数器的动作和减速器。此操作以快速间隔触发。减速器为每个动作返回一个新的状态副本。减速器看起来像:

import { handleActions } from 'redux-actions';
import { sceneTick } from './actions';

export default (state, action) => handleActions({
  [sceneTick]: (state, action) => {
    return {
      ...state,
      loop: action.payload,
    }
  },

在各种 React 组件上使用react-redux'sconnect方法。并非所有组件都关心这个循环计数器。因为我在每次滴答时都在减速器中返回一个新状态,所以所有订阅的组件connect都会mapDispatchToProps被执行,这会导致不必要的 React 渲染调用。

这些组件之一看起来像:

const mapStateToProps = (state, props) => {
  return {
    viewport: state.viewport,
    assets: state.assets,
  };
};


export default connect(mapStateToProps, {})(Component)

即使这个组件不依赖state.loop它,它也会被触发重新渲染。这会导致不需要重新渲染的组件中的重新渲染、过度渲染、多次渲染、不必要的渲染、性能问题和意外行为。

更新 我还应该补充一点,我没有combineReducers在这里使用并且所有减速器都应用于完整状态。不确定是否相关。

3个回答

Reduxconnect接受一个areStatesEqual函数选项,可用于将相等性检查范围缩小到特定的状态分支。

export default connect(
  {},
  {},
  null,
  {
    areStatesEqual: (next, prev) => {
      return (
        prev.branch === next.branch
      );
    }
  }
)(Component);
我确实想知道有多少人使用了重新选择,而本可以使用这种方法。+1
2021-06-16 21:04:36

根据 Redux 实现,它connect是纯的,因此对它需要提供给组件的 props 进行了浅层比较,即它shouldComponentUpdate在其实现中实现了一个方法,并且如果数据从mapStateToProps不会改变。

Redux 监控每个更改的状态更改很重要,因为只有它才能决定是否更新。

由于 Pure 组件对 state 和 props 进行了浅层比较,因此您应该确保您的状态不是高度嵌套的

您的选择器可能有问题,它每次都返回一个新对象,这将违反浅比较
2021-06-07 21:04:36
我一直无法重现这种行为。我不应该从 mapStateToProps 返回一个新对象吗?这不会使浅比较无效吗?
2021-06-20 21:04:36

如果是 redux 导致的性能问题,请使用 reactshouldComponentUpdate方法。

https://reactjs.org/docs/react-component.html#shouldcomponentupdate


更新:CombineReducers 会有所作为。尝试改变

return {
   ...state,
   loop: action.payload,
}

state.loop = ...action.payload;
return state;

如果你不想改变状态,你应该使用 combineReducer with loop 作为它自己的 reducer。由于您没有使用 combineReducer,我将状态转换为 rootReducer。它类似于 redux 作者对 combineReducers ( video )所做的,除了 nextState 是在 combineReducer 中创建的。

连接非常有效。如果 state.loop 未在组件中使用,则不会在 state.loop 上重新渲染。很可能另一个 Reducer 正在意外更新。Redux 开发工具在这种情况下很有帮助。
2021-05-26 21:04:36
@SILENT 我向 OP 添加了一个关于combineReducers不确定这里是否相关的更新
2021-06-03 21:04:36
这种方法需要shouldComponentUpdate在与更新状态分支无关的每个组件中进行检测,这需要付出很多努力。
2021-06-04 21:04:36
您无法停止使用shouldComponentUpdate. 那只是一个生命周期事件。
2021-06-11 21:04:36
@Andrew ShouldComponentUpdate 不会停止重新渲染,但如果由于属性中的传入更改(例如 redux 状态更改)而导致重新渲染,则可以减少重新渲染。
2021-06-19 21:04:36