如何防止 React with Hooks & Context 中的 child 组件出现不必要的 re-renders?

How can I prevent unnecessary re-renders on the child components in React with Hooks & Context?

我正在编写一些代码,这段代码非常庞大。我们有这么多 child 个组件(将近 300 个),每个组件都通过 React Context 使用和操作来自 parent 组件状态的值。

Note: I didn't wrote this code from scratch. Which also means the design I'm about to show is not what I would come up with.

问题: 因为每个组件都使用相同的状态,所以有很多不必要的 re-renders 发生。每个小的状态变化都会导致每个组件 re-render。它使网络应用程序变得迟钝。从字面上看,当您在字段中输入一些内容时会出现延迟。

我认为,当状态发生变化时,函数会被重建,这就是每个 child 都会更新的原因,因为上下文提供的值在状态发生变化后会发生变化。

此外,我尝试使用 useReducer 而不是 useState,但效果不佳。除此之外,我尝试在每个 child 组件上使用 React.memo,但是无论我尝试什么,compare 函数都没有被触发。 compare 函数仅在 parent 组件上触发,该组件具有状态作为道具。在这一点上,我什至不确定问题出在哪里 :D

为了提供有关设计的更多具体细节,以下是我们如何定义回调并将其传递给 child 组件。

定义:

const [formItemState, setFormState] = React.useState<FormItemState>({} as FormItemState);

const getAppState = useCallback(() => ({ state: props.state as AppState }), [props.state]);

const getAppAction = useCallback(() => ({ action: props.action as AppAction }), [props.action]);

const getFormItemError = useCallback((key: string) => formItemErrorState[key], [
  formItemErrorState,
]);

const getFormItem = useCallback((key: string) => formItemState[key], [formItemState]);

const updateFormItem = useCallback(
    (name: string, formItemData: FormItemData): void => {
        const previousState = getFormItem(name);
        if (!isEqual(previousState, formItemData)) {
            formItemState[name] = formItemData;
            setFormState((state) => ({
                ...state,
                ...formItemState,
            }));
        }
    },
    [formItemState, setFormState]
);

将它们传递给 Context.Provider:

return (
    <FormContext.Provider
        value={{
            getAppAction,
            getAppState,
            getFormItem,
            updateFormItem
        }}
    >
        <SomeComponent>
            {props.children} // This children contains more than 250 nested components, and each one of them are using these provided functions to interact with the state.
        </SomeComponent>
    </FormContext.Provider>
);

最后说明:如果需要更多信息,请询问我。谢谢!

为什么不直接将状态管理重写为 redux 并仅提取每个组件上使用的必要状态。 React.memo 只从 props 中提取变化