In React, How to Return JSX together with JS Function that returns more JSX?

In a React Component that renders a select field with options being dynamically created by a component function renderOptions(), how can we also render an empty option element (eg: <option value=""></option>) as the very first option?

React Code before adding the empty <option>

renderOptions() {
    return (
        this.props.users.map(user => (
            <option key={ user._id } value={ user._id }>{ user.name }</option>
        ))
    )
}


render() {
    return (
        <div>
            <div className="someDiv"></div>

            <select>
                { this.props.usersAreLoading 
                    ? <option value="">Loading...</option> 
                    : this.renderOptions()
                }            
            </select>
        </div>
    )
}

Failed Attempt

render() {
    return (
        <div>
            <div className="someDiv"></div>

            <select>
                { this.props.usersAreLoading 
                    ? <option value="">Loading...</option> 
                    : <option value=""></option> this.renderOptions()
                }            
            </select>
        </div>
    )
}

5 answers

  • answered 2018-10-11 19:17 Hemadri Dasari

    Try this

     <select>
            { this.props.usersAreLoading 
                    && <option value="">Loading...</option> }
            {!this.props.usersAreLoading && <option value=""></option>} 
            {!this.props.usersAreLoading && this.renderOptions()}           
       </select>
    

  • answered 2018-10-11 19:18 Eugene Tsakh

    You have to render it separately:

    {!this.props.usersAreLoading && <option value=""></option>}
    
    {this.props.usersAreLoading 
      ? <option value="">Loading...</option> 
      : this.renderOptions()
    } 
    

  • answered 2018-10-11 19:23 larrydahooster

    The simplest way (maybe not the most elegant) is to use two conditions

            <select>
                { this.props.usersAreLoading 
                    ? <option value="">Loading...</option> 
                    : <option value=""></option>
                } 
               {!this.props.usersAreLoading && this.renderOptions()
          } 
    
            </select>
    

  • answered 2018-10-11 19:32 estus

    Since ternary 'else' should contain multiple elements, they could be wrapped with React.Fragment:

    {this.props.usersAreLoading ? (
      <option value="">Loading...</option>
    ) : (
      <>
        <option value=""></option>
        {this.renderOptions()}
      </>
    )}
    

    Or provided as single array:

    {this.props.usersAreLoading ? (
      <option value="">Loading...</option>
    ) : [
      <option value=""></option>,
      this.renderOptions()
    ]}
    

  • answered 2018-10-11 19:39 Nikhil

    Use Fragment to wrap the option components

    <select>
              {this.props.usersAreLoading ? (
                <option value="">Loading...</option>
              ) : (
                <Fragment>
                    <option value=""/>
                  {this.renderOptions()}
                </Fragment>
              )}
              )} }
     </select>