MarioD MarioD - 1 month ago 16
React JSX Question

JSX Inline function (programatically set?)

I want to check for a true value on a state and set a class accordingly. The code below does just this, However...

Is there a way to do this programatically, maybe through a for loop to add all of the inline function checks.

The reason for this is because there are instances where I have hundreds of items, and I would hate to repeat and paste the same code hundreds of times.

Any help would be greatly appreciated, Thanks!



class App extends React.Component {
constructor() {
super();

this.state = {
item1: false,
item2: true,
item3: false
}
}

render() {
return(
<div className="app">
<ul>
<li data-item="item1" className={(this.state.item1) ? "active" : null}>Item 1</li>
<li data-item="item2" className={(this.state.item2) ? "active" : null}>Item 2</li>
<li data-item="item3" className={(this.state.item3) ? "active" : null}>Item 3</li>
</ul>
</div>
);
}
}

ReactDOM.render(<App />, document.getElementById('app'));

.active {
color: green;
}

<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="app"></div>




Answer

If there are thousands of these, they should probably be in an array rather than an object. But we can get the object's property names as an array if necessary.

Using an array instead (see comments):

class App extends React.Component {
  constructor() {
    super();

    // Turning items into an array
    this.state = {
      items: [
        {name: "item1", label: "Item 1", state: false},
        {name: "item2", label: "Item 2", state: true},
        {name: "item3", label: "Item 3", state: false}
      ]
    };
  }
  
  render() {    
    return(
      <div className="app">
        <ul>
          {/* Loop through the items, outputting them*/}
          {this.state.items.map(item => (
            <li data-item={item.name} className={item.state ? "active" : null}>{item.label}</li>
          ))}
        </ul>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('app'));
.active {
  color: green;
}
<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="app"></div>

Using your existing object plus another object to give us the item labels (see comments):

class App extends React.Component {
  constructor() {
    super();
      
    this.state = {
      item1: false,
      item2: true,
      item3: false
    };
    
    // The labels we want on the items
    this.itemNames = {
      item1: "Item 1",
      item2: "Item 2",
      item3: "Item 3"
    };
  }
  
  render() {    
    return(
      <div className="app">
        <ul>
          {/* Loop through the items, outputting them*/}
          {Object.keys(this.state).map(key => (
            <li data-item={key} className={this.state[key] ? "active" : null}>{this.itemNames[key]}</li>
          ))}
        </ul>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('app'));
.active {
  color: green;
}
<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="app"></div>