使用键来识别 React.js 中的嵌套组件

Using keys to identify nested components in React.js

本文关键字:嵌套 组件 js React 识别      更新时间:2023-09-26

当组件从一个上下文"移动"到另一个上下文时,是否可以阻止它调用其所有生命周期?

最初,我有一个组件列表,由 id 键控。这很有用,因为当我对列表重新排序时,组件不会重新调用所有生命周期方法,它们只会"移动"。

很明显,我的设计必须从 [Widget] 移动到 [Row],其中 Row = [Widget]。项目现在在行之间移动,但始终具有相同的 ID。无论如何,当组件移动到新上下文时,将调用所有(包括组件WillMount)生命周期方法。

是否可以在整个渲染上下文中全局标识组件以防止此行为?还是我应该追求其他设计?

[       ][       ][       ] <- rows, don't care
 |||||||  |||||||  |||||||  <- significant
       ^ <- this
[      ][        ][       ] 
 ||||||  ||||||||  |||||||
         ^ <- should be able to move

文档中详细介绍了协调算法:http://facebook.github.io/react/docs/reconciliation.html

根据我对阅读它的理解,您无法完成您想要的:

在当前的实现中,您可以表达这样一个事实:一个 子树已在其同级之间移动,但您无法分辨 它已经搬到了别的地方。算法将重新渲染完整 子树。

一个可能的解决方案是将 Widget 组件与渲染位置分开生成。例如:

const WidgetContainer = () => {
  const widgetTree = useMemo(() => SOME_WIDGETS.reduce((tree, widget) => ({
    ...tree,
    [widget.name]: <widget.Widget someProps={someProps} />,
  }, {}), []);
  
  return (
    <Container>
      <Row1>
        {WIDGET_ROW1.map((widgetName) => widgetTree[widgetName])}
      </Row1>
    {/* etc... */}
    </Container>
  );
};

这意味着您的小部件将存储为预渲染的 JSX 片段,而不是每个周期都呈现。显然,您需要将任何适当的依赖项添加到 useMemo 调用中,这可能会消除任何好处,但假设widgetTree依赖项中不存在更改的唯一状态,那么这应该会阻止调用任何生命周期方法。

值得注意的是,当 JSX 片段添加到 widgetTree/从中删除 JSX 片段时,生命周期方法仍将调用。