How to handle state of multiple buttons with react?
15,204
I have created a simple example for you:
class App extends React.Component {
constructor() {
super();
this.onClick = this.onClick.bind(this);
this.state = {
arr: [
{ name: "first", isActive: true },
{ name: "second", isActive: true },
{ name: "third", isActive: true },
{ name: "fourth", isActive: true }
]
};
}
onClick(index) {
let tmp = this.state.arr;
tmp[index].isActive = !tmp[index].isActive;
this.setState({ arr: tmp });
}
render() {
return (
<div>
{this.state.arr.map((el, index) =>
<div key={index} onClick={() => this.onClick(index)}>
name: {el.name} / isActive: {el.isActive ? "true" : "false"}
</div>
)}
</div>
);
}
}
Check the fiddle and implement it in your case.
One more way to handle this is keeping the index of an active button in the state:
class App extends React.Component {
state = {
users: [
{ name: "John" },
{ name: "Sarah" },
{ name: "Siri" },
{ name: "Jim" },
{ name: "Simon" },
],
activeIndex: 0,
}
render() {
const { users, activeIndex } = this.state;
return (
<div>
{users.map((u, i) => (
<div
className={i === activeIndex ? 'active' : ''}
onClick={() => this.setState({ activeIndex: i })}
key={u.name}
>
{u.name}
</div>
))}
</div>
)
}
}
https://jsfiddle.net/846tfe3u/
Comments
-
Chris O almost 2 years
I have a bootstrap grid where each grid item is populated from an array of objects but after each grid item I would like to have a vote button. How could I achieve this with maintaining state on each button separately, ie when button 1 is clicked the text should change from 'vote' to 'voted' whilst the others remain as 'vote'.
At the moment when a button is clicked, all of them change to 'Voted'
class Items extends Component { constructor(props) { super(props); this.state = { hasVoted: false }; this.OnClick = this.OnClick.bind(this); } OnClick() { this.setState(prevState => ({ hasVoted: !prevState.hasVoted })); } render() { const Item = teasers.items.map(item => <Col key={item.nid}> <span> {itemType} </span> <a href={item.path}> <Image src={item.image.src} title={item.productType} /> <span> {item.Title} </span> <div className={teasersStyle.copy}> {" "}{item.Copy}> </div> </a> <div className={this.state.hasVoted ? "active" : "notactive"} onClick={this.OnClick} > {this.state.hasVoted ? "Voted" : "Vote"} </div> </Col> ); return ( <div> <Grid> <Row> {Item} </Row> </Grid> </div> ); } } export default Items;