如何将传入的Link组件props作为JSX包装器进行渲染?
如何用传入的React元素作为容器包裹内容
我有一个组件,接收的props中包含一组子项,每个子项带有一个已实例化的Link组件(或其他组件):
children: [ { id: '1', isActive: false, label: 'Forms', icon: <DestinationsIcon height={30} width={30} />, link: <Link to={'somewhere'} />, }, ]
在接收该props的组件中,原本用div包裹label的写法可以正常运行:
<List> {React.Children.map(children, (child) => { if (!React.isValidElement(child)) { return null; } return React.cloneElement(child, { children: <div>{child.props.label}</div>, }); })} </List>
但我想把div替换成子项自带的link元素来包裹label,直接写<child.props.link>{child.props.label}</child.props.link>无法生效,尝试React.createElement(child.props.link)也不行——因为createElement的第一个参数需要是组件构造函数或HTML标签名,而这里传入的是已创建的React元素实例。而且必须使用传入的这个带自身上下文的Link元素,不能重新创建。
解决方案
因为child.props.link已经是一个React元素实例,我们需要用React.cloneElement来克隆它,同时为其添加新的子内容(也就是label),这样既保留原link元素的所有props(比如React Router Link的to属性),又能将label作为它的子元素渲染。
修改后的代码如下:
<List> {React.Children.map(children, (child) => { if (!React.isValidElement(child)) { return null; } // 克隆传入的link元素,将label作为子内容传入 const wrappedLabel = React.cloneElement( child.props.link, {}, // 保留原link的所有props,如需覆盖可在这里添加 child.props.label ); return React.cloneElement(child, { children: wrappedLabel, }); })} </List>
如果原link元素本身已经带有子内容,且你希望保留这些内容并追加label,可以将第三个参数改为数组形式:
const wrappedLabel = React.cloneElement( child.props.link, {}, [...child.props.link.props.children, child.props.label] );
内容的提问来源于stack exchange,提问作者sir-haver
相关产品推荐
相关产品推荐

