Search code examples
reactjsconditional-rendering

How to conditionally render an attribute of state


I'm trying to get a dropdown menu to display the name of the topic that a user selected from a previous page (currently, it defaults back to 'Topics').

While I'm able to get $r.state.topics[$r.state.topicSelected].name in the console, I get an undefined error when I put this.state.topics[this.state.topicSelected].name in my code.

So, I'm trying to use conditional rendering to have 'Topics' render as a default while the topics themselves are gathered with a fetch request.

<select
value={this.state.topicSelected}
onChange={this.onTopicClick}
className="sort"
data-element>
    {
    // Add this option in the .then() when populating siteCategories()
    [<option key={this.state.topicSelected}
      value={this.state.topicSelected}>({if 
       (this.state.topics[this.state.topicSelected].name == undefined) {
       'Topics'
    } else {
    this.state.topics[this.state.topicSelected].name
     }})
    </option>].concat(
this.state.topics.map(function (topic) {
 return (<option
 key={topic.id}
 value={topic.id}>{topic.name}</option>);
  }))
 }
</select>

I'm getting a unexpected token error, but I've tried various combinations of syntaxes with no luck - how do I properly run this conditional formatting?


Solution

  • You can use a ternary expression ? :. Like so,

    this.state.topics[this.state.topicSelected] ? this.state.topics[this.state.topicSelected].name : 'Topics'
    

    Since undefined is a falsy value, it will return 'Topics' when this.state.topics[this.state.topicSelected] is undefined.

    <select
      value={this.state.topicSelected}
      onChange={this.onTopicClick}
      className="sort"
      data-element>
          <option key={this.state.topicSelected}
            value={this.state.topicSelected}>
            {this.state.topics[this.state.topicSelected] ?
             this.state.topics[this.state.topicSelected].name : 'Topics'}
          </option>
          {this.state.topics.map(function (topic) {
             return (<option key={topic.id} value={topic.id}>{topic.name}</option>);
          })}
    </select>
    
    

    With the way you have done things, there are some other problems as well, but I didn't see them as relevant to your question. For one, you are changing the first option of the list to be your selected value. Instead, you should be setting the value of the select which automatically selects the correct option from the list. Here's how I would write this:

    render() {
    <select
      value={this.state.topicSelected}
      onChange={this.onTopicClick}
      className="sort"
      data-element>
          <option value={0}>Topics</option>
          {this.state.topics.map(topic => 
                 <option key={topic.id} value={topic.id}>{topic.name}</option>))}
    </select>
    }