React Click Counter: Updating State of just one element
Solution 1
This is more of an issue of learning how to think in react.
If you need to be able to reuse a piece of functionality like a counter, you can make it its own component and have it manage its own state. Then you can reuse it wherever you need.
Here's an example:
class Counter extends React.Component {
state = {
count: 0
};
handleClick = () => {
// Use updater function when new state is derived from old
this.setState(prev => ({ count: prev.count + 1 }));
};
render() {
return (
<button className="block" onClick={this.handleClick}>
<div className="counter">{this.state.count}</div>
</button>
);
}
}
// Now you can use it dynamically like this:
class Block extends React.Component {
render() {
return (
<div>
<div>There are 4 counter component instances that each manage their own state.</div>
{[1,2,3,4].map(v => <Counter />)}
</div>
);
}
}
ReactDOM.render(<Block />, document.getElementById('root'));
<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="root"></div>
Solution 2
you should define two state and when press each button update the current state and you can render the current state in the dome like this
state = {
firstCount: 0,
secondCount: 0
}
and write your action (function) to handle update state like this
handleUpdateCount = stateName => {
this.setState({
[stateName]= this.state[stateName] + 1
})
}
then you should called this function like this =>
this.handleUpdateCount('firstCount')
Solution 3
If your buttons are dynamic you can set your state to be an array and update the relevant index
class Block extends React.Component {
state = [];
handleClick = index => {
this.setState(state => {
const newState = [...state]; //keep state immutable
!newState[index] && (newState[index] = 0)
newState[index]++
return newState
});
};
render() {
return (
<div>
{[1,2,3].map((value, index) => <button className="block" onClick={() => this.handleClick(index)}>
<div className="counter">{this.state[index]}</div>
</button>)}
</div>
);
}
}
Related videos on Youtube
adp
Updated on June 04, 2022Comments
-
adp almost 2 years
This should be pretty simple, but I can't figure out how to do it.
I have a component with multiple buttons, each with a "count" value, set with state. When a user clicks, the count goes up.
Right now, when I click one of the buttons, both counters change. How can I make it so only the div that was clicked updates, using the same state?
Edit: I don't want to have different counts, as I'd like for this component to render buttons dynamically. What if I don't know how many buttons I'll have at first?
class Block extends React.Component { state = { count: 0 }; handleClick = e => { const count = this.state.count; this.setState({ count: count + 1 }); }; render() { return ( <div> <button className="block" onClick={this.handleClick}> <div className="counter">{this.state.count}</div> </button> <button className="block" onClick={this.handleClick}> <div className="counter">{this.state.count}</div> </button> </div> ); } }
-
jonrsharpe about 4 yearsWhy did you think only one would change? You need to have two separate counts in that component, or two components each with their own count.
-
adp about 4 yearswell, that's what I was trying to avoid... because what if my buttons were dynamic and I don't know the right amount of buttons I'll end up with from the beginning? @jonrsharpe
-
jonrsharpe about 4 yearsHave the state be an array, and address them by index? Or, again, have each one manage its own state.
-
-
Jorge Mauricio almost 3 yearsOne correction...[stateName]= this.state[stateName] + 1 should be [stateName]: this.state[stateName] + 1 change = to :