【问题标题】:Objects are not valid as a React child (found: object with keys {children})对象作为 React 子对象无效(找到:带有键 {children} 的对象)
【发布时间】:2021-06-28 21:33:15
【问题描述】:

我读过一篇有趣的文章,它建议使用自定义 usechildProps 挂钩直接在父级中写入动态元素,而不是发送道具。文章在这里:https://medium.com/the-guild/the-coolest-most-underrated-design-pattern-in-react-cd6210956203

基本上不用写:

<Modal
  showCloseButton
  showDismissButton
  showActionButton
  title="Modal title"
  contents="Modal body text goes here."
  dismissButtonText="Close"
  actionButtonText="Save changes"
  handleDismiss={close}
  handleAction={save}
/>

可以写:

<Modal>
  <title>Modal title</title>
  <contents>Modal body text goes here.</contents>
  <dismissButton onClick={close}>Close</dismissButton>
  <actionButton onClick={save}>Save changes</actionButton>
</Modal>

所以,我试图重现作者给出的示例,但它不起作用。 React 声称:

对象作为 React 子级无效(找到:带有键 {children} 的对象)。如果您打算渲染一组子项,请改用数组。

useChildProp 钩子是:

import { useMemo } from "react";

const useChildProps = (children, whitelist) => {
  return useMemo(() =>
    [].concat(children).reduce(
      (childProps, child) => {
        if (whitelist && !whitelist.includes(child.type)) {
          throw Error(`element <${child.type}> is not supported`);
        }
        childProps[child.type] = child.props;
        return childProps;
      },
      [children]
    )
  );
};

export default useChildProps;

组件:

import useChildProps from "./useChildProps";

const ModalFromTheFuture = ({ children }) => {
  const childProps = useChildProps(children, [
    "title",
    "contents",
    "actionButton",
    "cancelButton"
  ]);

  return (
    <div>
      <header>{childProps.title && <h1> {childProps.title}</h1>}</header>
      <section>
        <p>{childProps.contents && childProps.contents}</p>
      </section>
      <footer>
        {childProps.actionButton && <button {...childProps.actionButton} />}
        {childProps.dismissButton && <button {...childProps.cancelButton} />}
      </footer>
    </div>
  );
};

export default ModalFromTheFuture;

如何解决这个问题?这种模式看起来很有趣。

我已阅读相关主题。我知道这个问题通常是由于没有破坏 props.children 引起的。但我已经在这里完成了。因此我的问题。

ps:这里也是一个沙盒:https://codesandbox.io/s/suspicious-tereshkova-8i0wm?file=/src/ComponentPattern.js:0-646

【问题讨论】:

  • 你在哪里使用useChildProps
  • 问题已更新,带有沙盒。问题似乎来自 childProps[child.type] = child.props; 行的 useChildProp 钩子。如果我用字符串替换 child.props,它就可以工作。
  • childProps.title 是一个对象。
  • 感谢沙盒,它让调试变得更加容易。
  • 这是一种奇怪的设计模式。我不明白你为什么不只是使用“正常”方式的 children 属性并制作一个接受 JSX 元素子元素的 Modal 元素,而不是使用这些伪元素,例如不存在的dismissButton。错误元素很可能会导致未捕获的错误,而 eslint 将不知道允许哪些元素。

标签: reactjs


【解决方案1】:

正如错误所说,您正在尝试将对象用作反应组件(childProp.titlechildProp.content)。看来您想将他们的孩子用作“内容”。

import { useMemo } from "react";

const useChildProps = (children, whitelist) => {
  return useMemo(() =>
    [].concat(children).reduce(
      (childProps, child) => {
        if (whitelist && !whitelist.includes(child.type)) {
          throw Error(`element <${child.type}> is not supported`);
        }
        childProps[child.type] = child.props;
        return childProps;
      },
      {})  // better make this an object, not an array that you were monkey-patching properties into
  );
};

export default useChildProps;
import useChildProps from "./useChildProps";

const ModalFromTheFuture = ({ children }) => {
  const childProps = useChildProps(children, [
    "title",
    "contents",
    "actionButton",
    "cancelButton"
  ]);
  console.log(childProps);
  delete childProps.actionButton.children;
  delete childProps.cancelButton.children;

  return (
    <div>
      <header>{childProps.title && <h1> {childProps.title.children}</h1>}</header>

      <section>
        <p>{childProps.contents && childProps.contents.children}</p>
      </section>

      <footer>
        {childProps.actionButton && <button {...childProps.actionButton} />}
        {childProps.dismissButton && <button {...childProps.cancelButton} />}
      </footer>
    </div>
  );
};

【讨论】:

    猜你喜欢
    • 2022-01-05
    • 1970-01-01
    • 2020-12-28
    • 2020-05-25
    • 2021-05-19
    • 2018-01-12
    • 2021-05-19
    • 2020-02-27
    • 2021-09-13
    相关资源
    最近更新 更多