Reputation: 21
I am trying to implement a counter for each of the elements in an array and display them on the screen. I have an array and I want to display the following for each of the elements: name of the car, likes, increase button, and decrease button. When I tried to increase and decrease the likes, all the elements gets increase and decrease the same way. How do I keep the likes independent from each other and not share the same likes? For example, when I like one car, I want only that one to increase the likes
count. Can someone assist me with this problem? This is my current code:
import React, {Component} from 'react';
class Cars extends Component {
constructor(props) {
super(props);
this.state = {
likes: 0
};
this.incFav = this.incFav.bind(this);
this.decFav = this.decFav.bind(this);
}
incFav(e) {
this.setState({likes: this.state.likes + 1});
}
decFav(e) {
this.setState({likes: this.state.likes - 1});
}
render() {
//Passed this.props.cars from another component. It is an array of cars.
const { cars } = this.props;
return (
<div>
{cars.map((car, key) => {
<li key={car}>
{car}
{this.state.likes}
<button onClick={this.incFav}>+</button>
<button onClick={this.decFav}>-</button>
</li>
})}
</div>
);
}
}
export default Cars;
Upvotes: 2
Views: 3878
Reputation: 5146
Alright, the answer is pretty straightforward. You are confusing the state of your list of cars with the state of each individual car. In this case you have a state for the component Cars
, but not for each specific car. My suggestion is to create an additional component called Car
, that has its own likes
. Your code would look something like this:
import React from 'react';
import Car from '../Car/Car.js';
const Cars = ({ cars }) => (
<ul>{cars.map((car, key) => <Car car={car} key={car} />}</ul>
);
export default Cars;
As you notice the Cars list does not need to have any info about the state of each single car, that's something you would handle inside each Car component like this:
import React, {Component} from 'react';
class Car extends Component {
constructor(props) {
super(props);
this.state = { likes: 0 };
this.incFav = this.incFav.bind(this);
this.decFav = this.decFav.bind(this);
}
incFav() {
this.setState(prevState => ({ likes: prevState.likes + 1 }));
}
decFav() {
this.setState(prevState => ({ likes: prevState.likes - 1 }));
}
render() {
return(
<li>
{this.props.car}
{this.state.likes}
<button onClick={this.incFav}>+</button>
<button onClick={this.decFav}>-</button>
</li>
);
}
}
export default Car;
As you may notice there is really not need in this scenario for a Cars
component so you can just embed this list in whichever part of your App directly, it's up to you. But having a separate component for each Car will guarantee you that they will have each a separate state with a separate counter for likes. Previously it was shared between all of them, make sure you understand why your code was not behaving as expected.
Upvotes: 2