I'm trying to change the value of like within the cardArr objects while using a map() to list each obj.
Below is my code. Current, it works, but every object shares the same counter since it's not calling from the object. I understand that I'm currently just calling the object property stored in state, but how do I edit the like in each object using a map function?
import React, { Component } from 'react';
const cardArr = [
{
id: 1,
text: "Hey this is a test.",
img: " ",
like: 0
},
{
id: 2,
text: "If this works I'll call it a day.",
img: " ",
like: 0
},
{
id: 3,
text: "I'll drink a lot of beer.",
img: " ",
like: 0
},
{
id: 4,
text: "Cheers",
img: " ",
like: 0
}
]
export class Card extends Component {
constructor(props) {
super(props);
this.state = {
like: 0,
show: true
};
// this.handleClick = this.handleClick.bind(this);
}
IncrementItem = () => {
this.setState({ like: this.state.like + 1 });
}
DecreaseItem = () => {
this.setState({ like: this.state.like - 1 });
}
// handleClick(e) {
// e.preventDefault();
// this.IncrementItem();
// }
// handleClick(e) {
// e.preventDefault();
// this.DecreaseItem();
// }
render() {
const cardList = (cardArr.map((card) =>
<ul>
<li>
<div key={card.id}>
{card.text};
<img src={card.img}/>
<p>Like Button</p>
<button onClick={this.handleClickAdd}>Like</button>
<p>Dilike Button</p>
<button onClick={this.DecreaseItem}>Disike</button>
<p>Likes: {this.state.like}</p>
</div>
</li>
</ul>
));
return(
<div id='card'>
{cardList}
</div>
)
}
}
To update an object in an array in React state: Use the map() method to iterate over the array. On each iteration, check if a certain condition is met. Update the object that satisfies the condition and return all other objects as is.
State can hold any kind of JavaScript value, including objects. But you shouldn't change objects that you hold in the React state directly. Instead, when you want to update an object, you need to create a new one (or make a copy of an existing one), and then set the state to use that copy.
To set your mind at ease, the onClick event does work with divs in react, so double-check your code syntax.
Move cardArr
to your component's state so on each onClick (like or deslike) you will be able to change like
prop as you want:
const Card = ({ card, onLike, onDeslike }) =>
<div>
{card.text}
<p>Likes: {card.like}</p>
<button onClick={() => onLike(card.id)}>Like</button>
<button onClick={() => onDeslike(card.id)}>Deslike</button>
</div>
class CardList extends React.Component {
constructor(props) {
super(props)
this.state = {
cards: [
{
id: 1,
text: 'Hey this is a test.',
img: ' ',
like: 0,
},
{
id: 2,
text: "If this works I'll call it a day.",
img: ' ',
like: 0,
},
{
id: 3,
text: "I'll drink a lot of beer.",
img: ' ',
like: 0,
},
{
id: 4,
text: 'Cheers',
img: ' ',
like: 0,
},
]
}
this.handleLike = this.handleLike.bind(this)
this.handleDeslike = this.handleDeslike.bind(this)
}
handleLike(id) {
this.setState(prevState => ({
...prevState,
cards: prevState.cards.map(card => ({
...card,
like: card.id === id ? card.like + 1 : card.like
}))
}))
}
handleDeslike(id) {
this.setState(prevState => ({
...prevState,
cards: prevState.cards.map(card => ({
...card,
like: card.id === id ? card.like - 1 : card.like
}))
}))
}
render() {
return (
<div>
<ul>
{this.state.cards.map(card =>
<li key={card.id}>
<Card
card={card}
onLike={this.handleLike}
onDeslike={this.handleDeslike}
/>
</li>
)}
</ul>
</div>
)
}
}
ReactDOM.render(
<CardList />,
document.getElementById('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>
Don't forget that setState is asynchronous and, therefore, you won't have it's latest changes right away.
What about to make separation. Create an additional component for cardAddr
. And move the render and like
working logic to CardAddr
component.
const cardArr = [
{
id: 1,
text: "Hey this is a test.",
img: " ",
like: 0
},
{
id: 2,
text: "If this works I'll call it a day.",
img: " ",
like: 0
},
{
id: 3,
text: "I'll drink a lot of beer.",
img: " ",
like: 0
},
{
id: 4,
text: "Cheers",
img: " ",
like: 0
}]
class CardAddr extends React.Component {
constructor(props) {
super(props);
this.state = this.state = props.card;
}
IncrementItem = () => {
this.setState({ like: this.state.like + 1 });
}
DecreaseItem = () => {
this.setState({ like: this.state.like - 1 });
}
render() {
return (
<div key={this.state.id}>
{this.state.text}
<img src={this.state.img}/>
<p>Like Button</p>
<button onClick={this.IncrementItem}>Like</button>
<p>Dilike Button</p>
<button onClick={this.DecreaseItem}>Disike</button>
<p>Likes: {this.state.like}</p>
</div>
)
}
}
class Card extends React.Component {
constructor(props) {
super(props);
this.state = {
show: true
};
}
render() {
const cardList = (cardArr.map((card) =>
<ul key={card.id}>
<li>
<CardAddr card={card}/>
</li>
</ul>
));
return(
<div id='card'>
{cardList}
</div>
)
}
}
ReactDOM.render(
<Card />,
document.getElementById('container')
);
<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="container">
</div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With