Issue
When clicking on the card's favorite icon, I need to favorite only one card at a time, however, this does not happen. For example, if I click on the first card on any page, all other first cards are bookmarked. So I have the problem of cards being favorited per page and I want only what I clicked to be favorited.
To solve the problem in App.tsx -> CardAction I put the following code.
<Button size="small">
<FavoriteIcon
onClick={() => changeColorFavorite(id)}
style={{ color: iconFavorite[id] ? "red" : "gray" }}
Favorite
</Button>
I declared a useState by looping through the data(.json file) and setting false as the initial value for each card.
const [iconFavorite, setIconFavorite] = useState(
[...Array(data.length).keys()].map((i) => false)
);
I also declared a function to change the state between true or false
const changeColorFavorite = (id: number) => {
const newIconFavorite = iconFavorite.slice();
newIconFavorite[id] = !iconFavorite[id];
setIconFavorite(newIconFavorite);
};
How to solve this problem? Can someone help me please? Follow the code in codesandbox.
Solution
Why it happened
The id
passed to changeColorFavorite
is actually the index
of the array being mapped, hence the same order of card is marked as favorite on every page.
The function you used for the this map:
{_DATA.currentData().map((item, id) =>
It defines id
as the index
of item
in this array. The actual value you are looking for should be item.id
.
Solution
Instead, pass item.id
should get the desired result:
onClick={() => changeColorFavorite(item.id!)}
(I have to add !
to override type check here, but you can refactor the data
type later to make sure id
is mandatory and is never undefined
)
On top of that, the onClick
is currently on your FavoriteIcon
, but you might want to move it to the Button
so that it does not just trigger by clicking on the icon:
<Button size="small" onClick={() => changeColorFavorite(item.id!)}>
<FavoriteIcon style={{ color: iconFavorite[item.id!] ? "red" : "gray" }} />
Favorite
</Button>
Hopefully this achieves the desired result without major changes.
That being said, I would suggest that the implementation of favorites could use some reconsideration in the future, if you need to expand more feature for those cards for example.
Small refactor
It seems that you're defining an array of false
like this, and an error message occurs:
const [iconFavorite, setIconFavorite] = useState(
[...Array(data.length).keys()].map((i) => false)
);
Despite that there might be better solution than handling these states as an array of Boolean
, at this moment you could refactor the above code into this:
const [iconFavorite, setIconFavorite] = useState([...data].fill(false))
It does the same but cleaner and without error syntax.
Hope this will help!
Answered By - John Li
Answer Checked By - - Robin (ReactFix Admin)