Vanludvig
Vanludvig

Reputation: 106

Disable button based on unique key in React?

I have multiple buttons that are rendered for multiple items. All the buttons have a unique id that I passed to the key, and I'm trying to disable the button based on the unique ID. The disable boolean is in the state, and when the button is clicked I want it to disable that one unique button.

However, the code I have disables all of the buttons that are rendered.

I've used map to access the parks items array in my state, so I'm not sure how I'd map over the buttons if I turned them into an array with unique keys in the state.

Here's what I have so far:

My state:

this.state = {
  parks: [],
  todos: [],
  disabled: false
};

The button:

<button
 key={item.id} //this id is coming from the mapped array "parks" state
 disabled={this.state.disabled}
 onClick={() =>
    this.setState({
    todos: [...this.state.todos, item.name], //this adds the parks 
                                             //state items to the todos 
                                             //state array
    disabled: true
      })
    }
  >

Upvotes: 1

Views: 3922

Answers (2)

Alvin Theodora
Alvin Theodora

Reputation: 946

You can achieve it by making the disabled state into arrays that contains the items' id.

Then in line disabled={this.state.disabled.indexOf(item.id)!==-1}, it checks whether the current button exists in the disabled array, .indexOf method returns -1 if the value to search for never occurs.

class TodoApp extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
    	parks: [
      	{id: 'a', name: "Learn JavaScript" },
        { id: 'b',name: "Learn React" },
        { id: 'c',name: "Play around in JSFiddle"},
        {id: 'd', name: "Build something awesome" }
      ],
      todos: [],
      disabled: [],
    }
  }
  
  render() {console.log('todos', this.state.todos)
    return (
      <div>
        <h2>Todos:</h2>      
        {this.state.parks.map(item => (
          <button
           key={item.id} //this id is coming from the mapped array "parks" state
           disabled={this.state.disabled.indexOf(item.id)!==-1}
           onClick={() =>
              this.setState({
                  todos: [...this.state.todos, item.name], 
                  disabled: [...this.state.disabled, item.id]
                })
              }
          >
            {item.name}
          </button>
        ))}
   
      </div>
    )
  }
}

ReactDOM.render(<TodoApp />, document.querySelector("#app"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="app"></div>

Upvotes: 5

manonthemat
manonthemat

Reputation: 6251

Instead of using a boolean, you can use an array, where you keep track of the ids that you want to have disabled (= that you clicked on).

In the onClick handler, you add the id of the button to the disabled array within state. For the buttons, you then just check if the item.id is in the this.state.disabled array.

Upvotes: 0

Related Questions