ReactFix
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • React
  • React Native
  • Programming
  • Object Oriented Programming

Wednesday, November 16, 2022

[FIXED] How to solve the problem of a card being bookmarked by page using react, typescript and mui?

 November 16, 2022     frontend, json, material-ui, reactjs, typescript   

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.

Code codesandbox here


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.

More about map()

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.

More about fill()

Hope this will help!



Answered By - John Li
Answer Checked By - - Robin (ReactFix Admin)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Google+
  •  Stumble
  •  Digg
Newer Post Older Post Home

Featured Post

Is Learning React Difficult?

React is difficult to learn, no ifs and buts. React isn't inherently difficult to learn. It's a framework that's different from ...

Total Pageviews

Copyright © ReactFix