如何动态地将 React Web 组件添加到父组件?

How can I add React web components to a parent component dynamically?

假设我有一堆 React 网络组件

const ComponentA = () => {
  return (<div>A</div>)
}
const ComponentB = () => {
  return (<div>B</div>)
}
const ComponentC = () => {
  return (<div>C</div>)
}
const ComponentD = () => {
  return (<div>D</div>)
}
const ComponentE = () => {
  return (<div>E</div>)
}

我有一个父组件可以渲染其中的一些。

export default function () {
  const [state, setState] = useState({ count: 0, initialized: false, components: [ComponentA, ComponentB, ComponentC] });
  return (
    <FlexLayout>
      {state.components.map((comp, i) => React.createElement(comp, { key: i }))}
    </FlexLayout>
  );
}

这是有效的,因为我可以看到我的三个组件 A、B 和 C 已正确呈现。接下来,我添加一个按钮来动态添加新项目。

export default function () {
  const [state, setState] = useState({ components: [ComponentA, ComponentB, ComponentC] });
  const handler = () => 
  {
    const list = state.components.slice(0);
    list.push(ComponentD);
    setState ({ components : list })
  }

  return (
    <FlexLayout>
      <button onClick={() => setState(handler)}>Add Component</button>
      {state.components.map((comp, i) => React.createElement(comp, { key: i  }))}
    </FlexLayout>
  );
}

这在我第一次点击按钮时也有效。我可以看到我已经添加了 ComponentD 。但是,如果我尝试再添加一个 ComponentD 实例,应用程序会崩溃并出现以下错误:

是什么导致我的组件不再对父级可用的范围丢失?

一些反馈:

  • 将整个组件存储在状态中是一种反模式。相反,将 ID 存储在状态中。更简单的状态将减少错误的可能性。
  • 正如 @Mary 所说,您的处理程序分配不正确。

这是一个工作示例:

const ComponentA = () => {
  return (<div>A</div>)
}
const ComponentB = () => {
  return (<div>B</div>)
}
const ComponentC = () => {
  return (<div>C</div>)
}
const ComponentD = () => {
  return (<div>D</div>)
}

const componentMap = {
  a: ComponentA,
  b: ComponentB,
  c: ComponentC,
  d: ComponentD,
}

export default function () {
  const [components, setComponents] = useState([
    'a','b','c',
  ]);
  const handler = () => {
    setComponents ( [...components, 'd'] );
  }

  return (
    <FlexLayout>
      <button onClick={handler}>Add Component</button>
      {components.map(ID => {
        const Component = componentMap[ID];
        return <Component key={ID}/>
      })}
    </FlexLayout>
  );
}

Live Demo