最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Pass props to the first child using this.props.children - Stack Overflow

programmeradmin3浏览0评论

I know the way we pass props to children when using this.props.children the following way:

React.Children.map(this.props.children, (child: any, index: number) => {
    return React.cloneElement(child, {
                Visibility: this.state.visibility,
        });
});

To pass prop to only the first child I can use the index and wrap the cloneElement call in an if (index === 0), but this won't stop map from interating over all the children.

I'm wondering if there's a way I can break the loop right after index 0 is reached. Thanks!

I know the way we pass props to children when using this.props.children the following way:

React.Children.map(this.props.children, (child: any, index: number) => {
    return React.cloneElement(child, {
                Visibility: this.state.visibility,
        });
});

To pass prop to only the first child I can use the index and wrap the cloneElement call in an if (index === 0), but this won't stop map from interating over all the children.

I'm wondering if there's a way I can break the loop right after index 0 is reached. Thanks!

Share Improve this question asked Jun 15, 2018 at 6:15 blankfaceblankface 6,35724 gold badges74 silver badges121 bronze badges 1
  • If you only render the first child, what about the other children? – T.J. Crowder Commented Jun 15, 2018 at 6:25
Add a ment  | 

2 Answers 2

Reset to default 4

I'm wondering if there's a way I can break the loop right after index 0 is reached. Thanks!

Don't use map at all, then, if you only want the first child.

const child = (Array.isArray(this.props.children) ? this.props.children[0] : this.props.children) || null;
return child && React.cloneElement(
    child,
    {Visibility: this.state.visibility }
);

That first bit:

const child = (Array.isArray(this.props.children) ? this.props.children[0] : this.props.children) || null;

...guards against the fact that this.props.children is only an array when there are multiple children (details); otherwise, it's the single child passed, or undefined if no children are passed (which we convert to null so we can directly return it from render).

Then the return child && guards aginst the possibility there were no children at all.

Example with all those situations:

class Example extends React.Component {
  constructor(...args) {
    super(...args);
    this.state = {
      visibility: true
    };
  }
  render() {
    const child = (Array.isArray(this.props.children) ? this.props.children[0] : this.props.children) || null;
    return child && React.cloneElement(
        child,
        {Visibility: String(this.state.visibility) }
    );
  }
}

const Child = props => <div>Visibility: {props.Visibility}</div>;

ReactDOM.render(
  <div>
    <Example />
    <Example><Child/></Example>
    <Example><Child/><Child/></Example>
  </div>,
  document.getElementById("root")
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react/15.1.0/react-dom.min.js"></script>

Since you only need the the first item, there is no need to loop through them.

React.Children.toArray() will always give you an array, regardless if you have one or multiple children, which saves you some of the checks in T.J's answer.

So here is a slightly shorter (and imo cleaner) solution:

  const child = React.Children.toArray(children)[0];
  if (child) {
    return React.cloneElement(child, {Visibility: this.state.visibility});
  }
  return null;

React.Children.toArray(children)

Returns the children opaque data structure as a flat array with keys assigned to each child. Useful if you want to manipulate collections of children in your render methods, especially if you want to reorder or slice this.props.children before passing it down.

发布评论

评论列表(0)

  1. 暂无评论