Home > OS >  Change of icon in favorites
Change of icon in favorites

Time:03-31

I try to change the icon and add it to favorites when I click on it. It works fine, my icon is changed but it impacts all my images icons instead of one. How can I fix this? Here is my code:

import React, { useState, useEffect } from "react";

import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline';
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';
import ExpandCircleDownIcon from '@mui/icons-material/ExpandCircleDown';
import PlayCircleIcon from '@mui/icons-material/PlayCircle';

const Row = () => {
    const [image, setImage] = useState([])
    const [favorite, setFavorite] = useState(false);

    useEffect(() => {
        ...
    }, []);

    const addToFavorite = () => {
       ...
    }

    return (
                <div >
                    {image.map((item) => {
                        return (
                            <div key={item.id}>
                                <span>{item.title}</span>
                                <span>{item.description}</span>
                                <img src={...} alt={image.title}/>
                                <div onClick={() => setFavorite(!favorite)}>
                                   {favorite ? < CheckCircleOutlineIcon onClick={() => addToFavorite()} /> : < AddCircleOutlineIcon onClick={() => addToFavorite()} />}
                                </div>
                        )
                     })}
                </div>
    );
}

export default Row;

CodePudding user response:

Your problem is favorite state is only true/false value, when it's true, all images will have the same favorite value.

The potential fix can be that you should check favorite based on item.id instead of true/false value

Note that I added updateFavorite function for handling favorite state changes on your onClick

Here is the implementation for multiple favorite items

import React, { useState, useEffect } from "react";

import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline';
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';
import ExpandCircleDownIcon from '@mui/icons-material/ExpandCircleDown';
import PlayCircleIcon from '@mui/icons-material/PlayCircle';

const Row = () => {
    const [image, setImage] = useState([])
    const [favorite, setFavorite] = useState([]);

    useEffect(() => {
        ...
    }, []);

    const updateFavorite = (itemId) => {
       let updatedFavorite = [...favorite]
       if(!updatedFavorite.includes(itemId)) {
          updatedFavorite = [...favorite, itemId]
       } else {
          updatedFavorite = updatedFavorite.filter(favoriteItem => itemId !== favoriteItem)
       }
       setFavorite(updatedFavorite)
    }

    const addToFavorite = () => {
       ...
    }

    return (
                <div >
                    {image.map((item) => {
                        return (
                            <div key={item.id}>
                                <span>{item.title}</span>
                                <span>{item.description}</span>
                                <img src={...} alt={image.title}/>
                                <div onClick={() => updateFavorite(item.id)}>
                                   {favorite.includes(item.id) ? < CheckCircleOutlineIcon onClick={() => addToFavorite()} /> : < AddCircleOutlineIcon onClick={() => addToFavorite()} />}
                                </div>
                        )
                     })}
                </div>
    );
}

export default Row;

Here is the implementation for a single favorite item

import React, { useState, useEffect } from "react";

import AddCircleOutlineIcon from '@mui/icons-material/AddCircleOutline';
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline';
import ExpandCircleDownIcon from '@mui/icons-material/ExpandCircleDown';
import PlayCircleIcon from '@mui/icons-material/PlayCircle';

const Row = () => {
    const [image, setImage] = useState([])
    const [favorite, setFavorite] = useState(); //the default value is no favorite item initially

    useEffect(() => {
        ...
    }, []);

    const updateFavorite = (itemId) => {
       let updatedFavorite = favorite
       if(itemId !== updatedFavorite) {
          updatedFavorite = itemId
       } else {
          updatedFavorite = null
       }
       setFavorite(updatedFavorite)
    }

    const addToFavorite = () => {
       ...
    }

    return (
                <div >
                    {image.map((item) => {
                        return (
                            <div key={item.id}>
                                <span>{item.title}</span>
                                <span>{item.description}</span>
                                <img src={...} alt={image.title}/>
                                <div onClick={() => updateFavorite(item.id)}>
                                   {favorite === item.id ? < CheckCircleOutlineIcon onClick={() => addToFavorite()} /> : < AddCircleOutlineIcon onClick={() => addToFavorite()} />}
                                </div>
                        )
                     })}
                </div>
    );
}

export default Row;

CodePudding user response:

This is what you're looking for based on the code you've provided:

import { useState, useEffect } from "react";

const Item = ({ item }) => {
  const [favorite, setFavorite] = useState(false);

  const toggleFavorite = () => setFavorite((favorite) => !favorite);

  return (
    <div>
      <span>{item.title}</span>
      <span>{item.description}</span>
      <span onClick={toggleFavorite>
        {favorite ? "[♥]" : "[♡]"}
      </span>
    </div>
  );
};

const Row = () => {
  const [items, setItems] = useState([]);

  useEffect(() => {
    // use setItems on mount
  }, []);

  return (
    <div>
      {items.map((item) => <Item item={item} key={item.id} />)}
    </div>
  );
};

export default Row;

You can break up your code into smaller components that have their own states and that's what I did with the logic that concerns a single item. I've created a new component that has its own state (favorited or not).

  • Related