shu*_*ksh 7 javascript typescript reactjs typescript-typings
假设您有以下组件接受一个或多个子 JSX.Elements 并在使用React.cloneElement(child, { onCancel: () => {} }.
有问题的组件(摘录):
interface XComponentProps {
onCancel: (index: number) => void;
}
class XComponent extends React.Component<XComponentProps> {
render() {
const { onCancel } = this.props;
const children = typeof this.props.children === 'function' ?
React.cloneElement(this.props.children, { onCancel: () => onCancel() }) :
this.props.children.map((child, idx) => (
React.cloneElement(child, { onCancel: () => onCancel(idx) })
));
return <div>{children}</div>;
}
}
Run Code Online (Sandbox Code Playgroud)
正在运行的相关组件(摘录):
interface UserComponentProps { caption: string }
const UserComponent = (props: UserComponentProps) => (
<button onClick={props.onClose}>{props.caption || "close"}</button>
);
ReactDOM.render(
<XComponent onCancel={handleCancel}>
<UserComponent />
<UserComponent />
<UserComponent />
</XComponent>
);
Run Code Online (Sandbox Code Playgroud)
眼下TSC抱怨并UserComponent没有onCancel在它的道具界面定义,确实没有。一个最简单的解决方法是手动定义onCancel到UserComponentProps接口。
但是,我想在不修改子节点的 prop 定义的情况下修复它,以便组件可以接受任意一组 React 元素。在这种情况下,有没有办法定义返回元素的类型,这些元素在XComponent(父)级别传递了额外的隐式道具?
这不可能。无法静态地知道 UserComponent 从 ReactDOM.render 上下文中的父 XComponent 接收到哪些 props。
如果您想要类型安全的解决方案,请使用子函数:
这是XComponent定义
interface XComponentProps {
onCancel: (index: number) => void;
childrenAsFunction: (props: { onCancel: (index: number) => void }) => JSX.Element;
}
class XComponent extends React.Component<XComponentProps> {
render() {
const { onCancel } = this.props;
return <div>{childrenAsFunction({ onCancel })}</div>;
}
}
Run Code Online (Sandbox Code Playgroud)
现在你可以用它来渲染你UserComponent的
<XComponent onCancel={handleCancel} childrenAsFunction={props =>
<span>
<UserComponent {...props} />
<UserComponent {...props} />
</span>
} />
Run Code Online (Sandbox Code Playgroud)
这会很好地工作,我经常使用这种模式,没有任何麻烦。您可以重构 XComponentProps 以childrenAsFunction使用相关部分(onCancel此处的函数)键入 prop。