Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
255 views
in Technique[技术] by (71.8m points)

javascript - Return multiple React elements in a method without a wrapper element

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 it. I have a method that returns part of the render method, and that functions needs to return both a React element and some text. It's clearer through an example:

class Foo extends React.Component {
  _renderAuthor() {
    if (!this.props.author) {
      return null;
    }

    return [
      ' by ',
      <a href={getAuthorUrl(this.props.author)}>{this.props.author}</a>,
    ]; // Triggers warning: Each child in an array or iterator should have a unique "key" prop.

  render() {
    return (
      <div>
        {this.props.title}
        {this._renderAuthor()}
      </div>
    );
  }
}

I know the render method has to return exactly 1 React element. Using a helper method like this would trigger a warning, and fixing the warning (by adding keys) would make the code too convoluted. Is there a clean way to do this without triggering a warning?

Edit:

Another use case:

render() {
  return (
    <div>
      {user
        ? <h2>{user.name}</h2>
          <p>{user.info}</p>
        : <p>User not found</p>}
    </div>
  );
}

Edit 2:

Turns out this isn't possible yet, I wrote about 2 workarounds here: https://www.wptutor.io/web/js/react-multiple-elements-without-wrapper

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...