blankface
blankface

Reputation: 6347

Best way to update attribute of clicked item in React

I'm trying to test a functionality out where if you have a list of li with an attribute of aria-checked, clicking on one will toggle it to true, while turning the rest of the li's aria to false.

I have implemented it below:

class Parent extends React.Component {
  constructor(props){
    super(props);
    this.state = {checked: false, items:[]}
    this.clicky = this.clicky.bind(this);
  }

  clicky(e){
     this.setState({
       items: [...this.state.items, e.currentTarget]
     }, () => {
       this.state.items.map((item, index) => {
          if(index == this.state.items.length - 1){
            item.setAttribute("aria-checked", "true");
          }
          else{
            item.setAttribute("aria-checked","false");
          }
       })
     })
  }

  render() {
    return (
      <ul>
        <li
          aria-checked={this.state.checked}
          onClick={this.clicky}>item 1</li>
        <li 
          aria-checked={this.state.checked}
          onClick={this.clicky}>item 2</li>
        <li 
          aria-checked={this.state.checked}
          onClick={this.clicky}>item 3</li>
      </ul>
    )
  }
}

React.render(<Parent />, document.getElementById('app'));

So on click, the clicked item's aria will become true, while all the other once will turn false. I'm wondering if there is a better/more efficient way of getting the same result. Thanks.

Working version: https://codepen.io/anon/pen/QmeKEw?editors=0010

Upvotes: 1

Views: 1687

Answers (2)

Artem Mirchenko
Artem Mirchenko

Reputation: 2170

You can play around with indexes, set up you checkedIndex state key, and compare index of each item with state.checkedIndex:

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { checkedIndex: -1 };
  }

 render() {
    const items = [ 'item 1', 'item 2', 'item 3' ];
    return (
      <ul>
        {items.map((item, index) =>
          <li
            key={item}
            aria-checked={this.checkedIndex === index}
            onClick={() => this.setState({ checkedIndex: index })}
          >
            item 1
          </li>)}
      </ul>
    )
  }
}

React.render(<Parent/>, document.getElementById('app'));

Upvotes: 0

Arman Charan
Arman Charan

Reputation: 5797

See Intro To React for more info.

// App.
class App extends React.Component {

  // State.
  state = {
    checked: false,
    items: [1, 2, 3]
  }

  // Render.
  render = () => (
    <ul>
      {this.state.items.map(item => (
        <li aria-checked={this.state.checked == item} onClick={() => this.clicky(item)}>
          Item {item}
        </li>
      ))}
    </ul>
  )
  
  // Clicky
  clicky = item => console.log('Clicked:', item) || this.setState({checked: item})
  
}

ReactDOM.render(<App/>, document.querySelector('#root'))
<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="root"></div>

Upvotes: 1

Related Questions