给孩子编号

时间:2016-09-12 17:51:20

标签: javascript reactjs

我有一个菜单组件,我希望能够对此组件中的菜单项进行编号。 (然后使用菜单项编号来跟踪聚焦的菜单项并响应数字键盘按键。)

我目前的实现看起来像这样:

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;?或者有更好的方法来设计所有这些吗?

2 个答案:

答案 0 :(得分:2)

我认为SoupOfTheDayMenuItemMenuItem的包装器或返回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可以是MenuItemSoupOfTheDayMenuItem,没有任何问题。