首页 > 解决方案 > 对 redux 的任何更改都会存储我的原因组件以重新渲染

问题描述

我正在对我的 UI 进行一些测试,我注意到如果我的 redux 存储中的任何状态发生变化,我的组件(如下所示)将重新渲染并在 0 处使用嵌入式视频重新启动。如果我输入与 redux 连接的文本字段,它会重新安装,如果状态通知到达商店,它会重新安装,等等。

我不知道如何解决这个问题,我真的可以使用一些帮助来弄清楚如何解决这个错误。

tldr; 每次我的 redux 商店发生变化时,如何阻止我的 VideoPlayer 重新渲染?


零件

const MyComponent = () => {
...
// data used in the VideoPlayer is descructured from this variable:
const formState = useSelector(selectDynamicForm);

// renders output here in the same component
return (
...
 {sourceContentFound === false ? (
   <VideoPlayerDisabled />
 ) : (
   <VideoPlayerController
     title={title}
     description={description}
     sourceAddress={iframeURL}
     author={authorName}
     timeStamp={{ startTime: 0 }}
   />
 )}
)
...
}

表格切片

export const dynamicFormSlice = createSlice({
  name: 'dynamicForm',
  initialState,
  reducers: {
    updateField: (state, action) => {
      state = action.payload;
      return state;
    }
  },
});

export const selectDynamicForm = createSelector(
  (state: RootState): dynamicFormState => state.dynamicForm,
  dynamicForm => dynamicForm
);

statusHandlerSlice

我不认为这个组件做任何疯狂的事情,我说,但是当满足视频条件时,我会出现一个通知。当它返回时clearStatus,视频播放器重新启动。

export const statusHandlerSlice = createSlice({
  name: 'statusHandler',
  initialState,
  reducers: {
    setStatus: (state, action: PayloadAction<IStatusObject>) => {
      const { type, display, message } = action.payload;
      state.status = {
        ...action.payload,
        message: message.charAt(0).toUpperCase() + message.slice(1),
      };
      if (display === 'internal-only' || display === 'support-both') {
        statusLogger(type, message);
      }
    },
    clearStatus: state => {
      state.status = {
        type: 'success',
        data: {},
        message: '',
        display: 'internal-only',
        key: '',
      };
    },
  },
});

export const { setStatus, clearStatus } = statusHandlerSlice.actions;

export const selectStatus = (state: RootState): IStatusObject =>
  state.statusHandler.status;

标签: javascriptreactjsreduxredux-toolkit

解决方案


MyComponent每次 redux 存储状态更改时都会重新渲染,因为其中有一个选择器

您可以通过添加一个equalFn来阻止这种情况发生useSelector

您可以编写自己equalityFn的函数或使用支持深度比较的库中的一些现有函数。

例如:使用 lodashisEqual

import { isEqual } from 'lodash';
const MyComponent = () => {
...
// data used in the VideoPlayer is descructured from this variable:
const formState = useSelector(selectDynamicForm, isEqual);

默认情况下,useSelector使用shallow无法检测对象内部深层变化的比较,更改为深层比较函数isEqual将帮助您做到这一点,但不建议所有选择器使用,因为这会影响性能。

现场示例:

编辑 redux-useSelector-useDispatch-Sample (forked)


推荐阅读