我有一个菜单组件,我希望能够对此组件中的菜单项进行编号。 (然后使用菜单项编号来跟踪聚焦的菜单项并响应数字键盘按键。)
我目前的实现看起来像这样:
class Menu extends React.Component {
numberChildren() {
return _.chain(React.Children.toArray(this.props.children))
.filter()
.map((child, i) => React.cloneElement(child, {
number: i + 1
}))
.value();
}
render() {
return <div className="menu">{this.numberChildren()}</div>;
}
};
我使用React.cloneElement注入number
道具,并且我使用lodash的filter
来排除任何空子项。
这足以处理如下菜单:
<Menu>
<MenuItem>Salad</MenuItem>
<MenuItem>Grilled Chicken</MenuItem>
{!this.props.isOnDiet && <MenuItem>Ice Cream</MenuItem>}
</Menu>
然而,对于更复杂的孩子来说却失败了:
<Menu>
<MenuItem>Salad</MenuItem>
<SoupOfTheDayMenuItem/>
<MenuItem>Grilled Chicken</MenuItem>
</Menu>
SoupOfTheDayMenuItem
是一个包装器组件,它返回单个MenuItem
(也应该枚举)或null
。
即使SoupOfTheDayMenuItem
返回null,在调用lodash的filter
时它仍然是真的,所以它仍然会得到2号。
有没有办法说&#34;只为真正被渲染的孩子注入这个属性&#34;或者&#34;给我一组实际上呈现出某些东西的孩子&#34;?或者有更好的方法来设计所有这些吗?
答案 0 :(得分:2)
我认为SoupOfTheDayMenuItem
是MenuItem
的包装器或返回null
因此,您可以尝试过滤掉那些props.children
虚假的孩子,这意味着SoupOfTheDayMenuItem
返回null。
这应该做的工作:
numberChildren() {
return _.chain(React.Children.toArray(this.props.children))
.filter(child => child.type.displayName == 'MenuItem' || child.props.children)
.map((child, i) => React.cloneElement(child, {
number: i + 1
}))
.value();
}
答案 1 :(得分:0)
我显然没有为您的应用程序提供所有上下文,但也许更有意义的是将每个子项包装在一个包装MenuItemContainer
组件中,该组件处理所有索引和内容,然后让孩子组件只是做他们的目的。我所说的就是
class Menu extends React.Component {
render() {
return this.props.children.map((Child, i) => {
return (
<MenuItemContainer key={i}>
<Child/>
</MenuItemContainer>
)
}
}
};
然后Child
可以是MenuItem
或SoupOfTheDayMenuItem
,没有任何问题。