Reputation: 500
I have a component which has several cards and each card has a button. Here is the component:
import React, { useState, useEffect } from "react";
import "./App.css";
import { Card, Container, Row, Col, Button } from "react-bootstrap";
function ListItemComponent() {
let [responseData, setResponseData] = useState([]);
const [isFavorite, setIsFavorite] = useState(false);
useEffect(() => {
fetch("https://api.quotable.io/authors?limit=10&skip=20")
.then((res) => res.json())
.then((data) => {
console.log(data.results);
setResponseData(data.results);
});
}, []);
console.log({ responseData });
var testObject = { one: 1, two: 2, three: 3 };
// Put the object into storage
localStorage.setItem("testObject", JSON.stringify(testObject));
// Retrieve the object from storage
var retrievedObject = localStorage.getItem("testObject");
console.log("retrievedObject: ", JSON.parse(retrievedObject));
const handleClick = () => {
setIsFavorite((s) => !s);
};
return (
<div>
<Container>
<Row>
{responseData && responseData.length > 0 ? (
responseData.map((author) => {
return (
<Col xl={6} lg={6} md={12} sm={12} xs={12} key={author.link}>
<Card>
<Card.Body>
<p>
<b>Name:</b> {author.name}
</p>
<p>
<b>Bio:</b> {author.bio}
</p>
<a href={author.link}>Link</a>
{isFavorite ? (
<Button variant="danger" onClick={handleClick}>
Remove Favorite
</Button>
) : (
<Button variant="success" onClick={handleClick}>
Add Favorite
</Button>
)}
</Card.Body>
</Card>
</Col>
);
})
) : (
<p>No Data Found</p>
)}
</Row>
</Container>
</div>
);
}
export default ListItemComponent;
here is a gif of what is happening now:https://recordit.co/C8gUJ0ByRY. So now if I click on just one button all the buttons in all the cards get selected and changes to Remove Favorite
from Add Favorite
, but I want to change the text of the only button that is clicked not all of them.
Upvotes: 0
Views: 225
Reputation: 71
In your actual code, the isFavorit variable is used in all the elements of the list. You can change to this to make each object of the list possess the isFavorit variable and, this way, only the ones with isFavorite = true will change.
import React, { useState, useEffect } from "react";
import "./App.css";
import { Card, Container, Row, Col, Button } from "react-bootstrap";
function ListItemComponent() {
let [responseData, setResponseData] = useState([]);
useEffect(() => {
fetch("https://api.quotable.io/authors?limit=10&skip=20")
.then((res) => res.json())
.then((data) => {
console.log(data.results);
setResponseData(data.results.map((result) => ({...result,isFavorite:false})));
});
}, []);
console.log({ responseData });
var testObject = { one: 1, two: 2, three: 3 };
// Put the object into storage
localStorage.setItem("testObject", JSON.stringify(testObject));
// Retrieve the object from storage
var retrievedObject = localStorage.getItem("testObject");
console.log("retrievedObject: ", JSON.parse(retrievedObject));
const handleClick = (a) => {
const author = responseData.find(el => el._id === a._id);
author.isFavorite = !author.isFavorite;
const list = responseData.map(el => author._id === el._id ? author : el );
setResponseData(list);
// setIsFavorite((s) => !s);
};
return (
<div>
<Container>
<Row>
{responseData && responseData.length > 0 ? (
responseData.map((author) => {
return (
<Col xl={6} lg={6} md={12} sm={12} xs={12} key={author.link}>
<Card>
<Card.Body>
<p>
<b>Name:</b> {author.name}
</p>
<p>
<b>Bio:</b> {author.bio}
</p>
<a href={author.link}>Link</a>
{author.isFavorite ? (
<Button variant="danger" onClick={() => handleClick(author)}>
Remove Favorite
</Button>
) : (
<Button variant="success" onClick={() => handleClick(author)}>
Add Favorite
</Button>
)}
</Card.Body>
</Card>
</Col>
);
})
) : (
<p>No Data Found</p>
)}
</Row>
</Container>
</div>
);
}
export default ListItemComponent;
Upvotes: 1
Reputation: 2604
You should create an array of favorites, each item on the array will be connected with a button, like this:
const [favorites, setFavorites] = useState(Array(responseData.length).fill(false));
And when you click on button, you will send the index clicked button to toggle the favourite of the button:
const handleClick = (index) => {
setFavorites((favorites) => favorites.map((favorite, i) => {
if(i == index) return !favorite
else return favorite
}));
};
Your component:
import React, { useState, useEffect } from "react";
import "./App.css";
import { Card, Container, Row, Col, Button } from "react-bootstrap";
function ListItemComponent() {
let [responseData, setResponseData] = useState([]);
const [favorites, setFavorites] = useState(Array(responseData.length).fill(false));
useEffect(() => {
fetch("https://api.quotable.io/authors?limit=10&skip=20")
.then((res) => res.json())
.then((data) => {
console.log(data.results);
setResponseData(data.results);
});
}, []);
console.log({ responseData });
var testObject = { one: 1, two: 2, three: 3 };
// Put the object into storage
localStorage.setItem("testObject", JSON.stringify(testObject));
// Retrieve the object from storage
var retrievedObject = localStorage.getItem("testObject");
console.log("retrievedObject: ", JSON.parse(retrievedObject));
const handleClick = (index) => {
setFavorites((favorites) => favorites.map((favorite, i) => {
if(i == index) return !favorite
else return favorite
}));
};
return (
<div>
<Container>
<Row>
{responseData && responseData.length > 0 ? (
responseData.map((author,i) => {
return (
<Col xl={6} lg={6} md={12} sm={12} xs={12} key={author.link}>
<Card>
<Card.Body>
<p>
<b>Name:</b> {author.name}
</p>
<p>
<b>Bio:</b> {author.bio}
</p>
<a href={author.link}>Link</a>
{favorites[i] ? (
<Button variant="danger" onClick={handleClick}>
Remove Favorite
</Button>
) : (
<Button variant="success" onClick={handleClick}>
Add Favorite
</Button>
)}
</Card.Body>
</Card>
</Col>
);
})
) : (
<p>No Data Found</p>
)}
</Row>
</Container>
</div>
);
}
export default ListItemComponent;
Upvotes: 0
Reputation: 500
import React, { useState, useEffect } from "react";
import "./App.css";
import { Card, Container, Row, Col, Button } from "react-bootstrap";
function ListItemComponent() {
let [responseData, setResponseData] = useState([]);
const [isFavorite, setIsFavorite] = useState(false);
const [index, setIndex] = useState(false);
useEffect(() => {
fetch("https://api.quotable.io/authors?limit=10&skip=20")
.then((res) => res.json())
.then((data) => {
console.log(data.results);
setResponseData(data.results);
});
}, []);
console.log({ responseData });
var testObject = { one: 1, two: 2, three: 3 };
// Put the object into storage
localStorage.setItem("testObject", JSON.stringify(testObject));
// Retrieve the object from storage
var retrievedObject = localStorage.getItem("testObject");
console.log("retrievedObject: ", JSON.parse(retrievedObject));
const handleClick = (id) => {
setIsFavorite((s) => !s);
setIndex(id);
console.log(id);
};
return (
<div>
<Container>
<Row>
{responseData && responseData.length > 0 ? (
responseData.map((author) => {
return (
<Col xl={6} lg={6} md={12} sm={12} xs={12} key={author.link}>
<Card>
<Card.Body>
<p>
<b>Name:</b> {author.name}
</p>
<p>
<b>Bio:</b> {author.bio}
</p>
<a href={author.link}>Link</a>
{isFavorite && index === author.link ? (
<Button
variant="danger"
onClick={() => handleClick(author.link)}
>
Remove Favorite
</Button>
) : (
<Button
variant="success"
onClick={() => handleClick(author.link)}
>
Add Favorite
</Button>
)}
</Card.Body>
</Card>
</Col>
);
})
) : (
<p>No Data Found</p>
)}
</Row>
</Container>
</div>
);
}
export default ListItemComponent;
Upvotes: 0