Return multiple React elements in a method without a wrapper element

前端 未结 10 874
南方客
南方客 2020-12-16 13:06

I\'m trying to return multiple React elements from a helper method. I could solve it simply by moving around some code, but I\'m wondering if there\'s a cleaner way to solve

相关标签:
10条回答
  • 2020-12-16 13:53

    The error message tells you exactly how to solve this:

    Each child in an array or iterator should have a unique "key" prop.

    Instead of this:

    return [
      ' by ',
      <a href={getAuthorUrl(this.props.author)}>{this.props.author}</a>,
    ];
    

    Do this:

    return [
      <span key="by"> by </span>,
      <a key="author" href={getAuthorUrl(this.props.author)}>{this.props.author}</a>,
    ];
    

    Yes, you need to wrap the text node ("by") in a span in order to give it a key. Such are the breaks. As you can see, I've just given each element a static key, since there's nothing dynamic about them. You could just as well use key="1" and key="2" if you wanted.

    Alternatively, you could do this:

    return <span> by <a href={getAuthorUrl(this.props.author)}>{this.props.author}</a></span>;
    

    ...which obviates the need for keys.

    Here's the former solution in a working snippet:

    const getAuthorUrl = author => `/${author.toLowerCase()}`;
    
    class Foo extends React.Component {
      _renderAuthor() {
        if (!this.props.author) {
          return null;
        }
    
        return [
          <span key="by"> by </span>,
          <a key="author" href={getAuthorUrl(this.props.author)}>{this.props.author}</a>,
        ];
      }
    
      render() {
        return (
          <div>
            {this.props.datePosted}
            {this._renderAuthor()}
          </div>
        );
      }
    }
    
    ReactDOM.render(<Foo datePosted="Today" author="Me"/>, document.getElementById('container'));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <div id="container"></div>

    0 讨论(0)
  • 2020-12-16 13:53

    Try this approach on your array:

    return [
          <span key={'prefix-'+random_string_generator()}>' by '</span>,
          <a key={'prefix-'+random_string_generator()} href={getAuthorUrl(this.props.author)}>{this.props.author}</a>,
        ];
    
    0 讨论(0)
  • 2020-12-16 13:54

    Support has been added using the Fragment component. This is a first-class component.

    So you can now use:

    render() {
      return (   
        <React.Fragment>
          <ChildA />
          <ChildB />
          <ChildC />
        </React.Fragment>
      );
    }
    

    For more information visit: https://reactjs.org/blog/2017/11/28/react-v16.2.0-fragment-support.html

    0 讨论(0)
  • 2020-12-16 13:57

    Perhaps a more simple way would be to rethink how you're architecting your application. However, in a more simple way.

    You're triggering the warning because you're trying to render from an array and not react elements but directly html. In order to approach this, you would have to do

    {this._renderAuthor().map(
        (k,i) => (React.addons.createFragment({k}))
        )  }
    

    React addons createFragment function basically does that, it reduces your html elements into react fragments that you can render.

    React createFragment documentation

    Alternatively, in a much better approach, you can create an AuthorLink stateless component like this..

    function AuthorLink(props) {
      return (
        <div className="author-link">
          <span> by </span>
          <a href={props.authorUrl}> {props.author} </a>
        </div> 
      });
    }
    

    and use this in your main component's render

    render() {
      const { author } = this.props;
      return (
        <div>
          {this.props.datePosted}
          <AuthorLink url={getAuthorUrl(author)} author={author} />
        </div>
      );
    }
    
    0 讨论(0)
提交回复
热议问题