【发布时间】: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