Return multiple React elements in a method without a wrapper element

前端 未结 10 980
南方客
南方客 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:46

    You can return fragments from sub-rendering functions but not from the main render function, at least before React 16. In order to do so, return an array of components. You don't need to set keys manually unless your fragment children will change (arrays are keyed with indices by default).

    For creating fragments you may also use createFragment.

    For inline usage, you may use an array or leverage immediately invoked arrow function. See the example below:

    const getAuthorUrl = author => `/${author.toLowerCase()}`;
    
    class Foo extends React.Component {
      constructor() {
         super();
         this._renderAuthor = this._renderAuthor.bind(this);
         this._renderUser = this._renderUser.bind(this);
      }
      
      _renderAuthor() {
        if (!this.props.author) {
          return null;
        }
    
        return [
          ' by ',
          {this.props.author},
        ];
      }
      
      _renderUser() {
        return [
          

    {this.props.user.name}

    ,

    {this.props.user.info}

    ] } render() { return (
    {this.props.datePosted} {this._renderAuthor()}
    {this.props.user ? this._renderUser() :

    User not found

    }
    {this.props.user ? [

    {this.props.user.name}

    ,

    {this.props.user.info}

    ] :

    User not found

    }
    {this.props.user ? (() => [

    {this.props.user.name}

    ,

    {this.props.user.info}

    ])() :

    User not found

    }
    ); } } ReactDOM.render(, document.getElementById('container'));
    
    
    

    In order to not get warnings each child must be assigned a key. In order to do so, instead of returning an array please use helper function fragment(...children) to assign index-based keys automatically. Please note that strings must be converted to spans or other nodes that can be assigned with a key:

    const fragment = (...children) =>
        children.map((child, index) =>
            React.cloneElement(
                typeof child === 'string'
                ? {child}
                : child
            , { key: index }
            )
        )
    

    const getAuthorUrl = author => `/${author.toLowerCase()}`;
    
    const fragment = (...children) =>
        children.map((child, index) =>
            React.cloneElement(
                typeof child === 'string'
                ? {child}
                : child
            , { key: index }
            )
        )
    
    class Foo extends React.Component {
      constructor() {
         super();
         this._renderAuthor = this._renderAuthor.bind(this);
         this._renderUser = this._renderUser.bind(this);
      }
      
      _renderAuthor() {
        if (!this.props.author) {
          return null;
        }
    
        return fragment(
          ' by ',
          {this.props.author}
        );
      }
      
      _renderUser() {
        return fragment(
          

    {this.props.user.name}

    ,

    {this.props.user.info}

    ) } render() { return (
    {this.props.datePosted} {this._renderAuthor()}
    {this.props.user ? this._renderUser() :

    User not found

    }
    {this.props.user ? fragment(

    {this.props.user.name}

    ,

    {this.props.user.info}

    ) :

    User not found

    }
    {this.props.user ? (() => fragment(

    {this.props.user.name}

    ,

    {this.props.user.info}

    ))() :

    User not found

    }
    ); } } ReactDOM.render(, document.getElementById('container'));
    
    
    

提交回复
热议问题