当组件复杂如嵌套组件时,如何减少React中的重新渲染次数?

问题描述 投票:0回答:1

我在我的应用程序中使用 React 和 Redux Toolkit 进行状态管理,该应用程序具有嵌套的组件结构。假设我有三个主要组件:一个主包装组件、一个项目组件和一个子项目组件。子项组件也可以有多个嵌套子组件。 item 和子 item 组件都使用 useState、useEffect 和 useSelector 来管理和检索 Redux 中的数据。

所有数据都以对象数组的形式存储在 Redux 中,每个对象包含一个 level 字段(表示嵌套级别)和一个 prevId 字段(表示父数据)。我循环访问主包装器组件中的 Redux 数据,以使用 item 组件显示它。在项目组件中,我为任何直接子项目调用子项目组件(基于 prevId)。这种结构有点类似于组件的链表。

我面临的问题是,当我切换到编辑模式时,每个项目或子项目都会渲染多次(我已经使用 console.count 验证了这一点以跟踪重新渲染的次数),即使我没有尚未进行任何更改。

有人有类似问题的解决方案或指导吗?

我已经为组件内部可能的值实现了 useMemo,为组件本身实现了 React.memo,以防止不必要的重新渲染,但它似乎没有任何效果。

包装组件

const WrapperComponent = () => {
const ItemDataRedux = useSelector(selectItemDataRedux);
const ItemListData = useDebounce(ItemDataRedux, 450);

const memoizedItemData = useMemo(() => {
  return ItemListData?.filter((obj: Item) => obj.level === 1);
}, [ItemListData]);

return (
  <div>
    {memoizedItemData?.map((item: Item, index: number) => (
      <ItemComponent
        key={`list-of-step-${item.idid}`}
        idElement={item.idElement}
        typeElement={item.type}
        prevId={item.prevId!}
        level={1}
        name={item.name ?? ""}
        orderNumber={item.orderNumber}
        nextLogic={item.nextLogic}
        // in item component, i name it as nextLogicServer from props
        listItemChild={item?.listItemChild ?? []}
      />
    ))}
  </div>
  );
};
export default WrapperComponent;

项目组件

  const ItemDataRedux = useSelector(selectItemDataRedux);
  const [nextLogic, setNextLogic] = useState<nextLogicType>({
    GoNextLogic: nextLogicServer?.GoNextLogic ?? null,
  });
  const [nameElement, setNameElement] = useState<string>(name || "");

  useEffect(() => {
    // update the local nextLogic where parent changes
    setNextLogic({
        ...nextLogic,
        GoNextLogic: nextLogicServer?.GoNextLogic ?? null,
    });
  }, [nextLogicServer?.GoNextLogic]);

  useEffect(() => {
    const SaveData = () => {
        // update the data in redux selectItemDataRedux by idElement
        dispatch(
            updateElementByIdElement({
                idElement,
                nextLogic,
            })
        );
    };
    // v1 directly update
    // SaveData();

    // v2 delay by 0.2 second then update
    const timeoutId = setTimeout(() => {
        SaveData();
    }, 200);

    return () => {
        clearTimeout(timeoutId);
    };
  }, [nextLogic, idElement]);

updateElementByIdElement 用于更新

const ItemDataRedux = useSelector(selectItemDataRedux);

的父数据
reactjs performance optimization react-hooks rerender
1个回答
0
投票

看你在 useeffect 依赖中使用

idElement
并且你在其中映射一个数据,如果你传递了 100 个数据
idElement
它可以重新渲染 useeffect 并且它对应的函数 100 次,因此它可以做出反应显示你是渲染错误或项目崩溃。

© www.soinside.com 2019 - 2024. All rights reserved.