Estoy creando una aplicación para marcar personajes de Marvel (héroes), por lo que cuando hago clic en un icono de marcador específico, debe cambiar a un icono de marcador relleno y viceversa. Desafortunadamente, cuando hago clic en uno solo, todos los íconos cambian. Supongo que el problema está en el estado. ¡Por favor ayuda!
Como accesorio, recibo todos los datos sobre los personajes (imagen, nombre) Aquí está el código:
import React, { useState, useEffect } from "react"; import "./CharactersList.css"; import { RiBookmarkLine } from "react-icons/ri"; import { RiBookmarkFill } from "react-icons/ri"; const CharactersList = (props) => { const [isLiked, setisLiked] = useState(false); const [toggle, setToggle] = useState(false); const [favourites, setFavourites] = useState([]); useEffect(() => { const bookMarkedData = JSON.parse( localStorage.getItem("react-bookmarked-characters") ); if (bookMarkedData) { setFavourites(bookMarkedData); } }, []); const saveToLocalStorage = (data) => { localStorage.setItem("react-bookmarked-characters", JSON.stringify(data)); }; const handleBookmarking = (character) => { if (toggle === true) { const newBookmarkedList = [...favourites, character]; setFavourites(newBookmarkedList); saveToLocalStorage(newBookmarkedList); setisLiked(true); } else { const newBookmarkedList = favourites.filter( (favourites) => favourites.id !== character.id ); setFavourites(newBookmarkedList); saveToLocalStorage(newBookmarkedList); setisLiked(false); } }; const toggleLike = () => { setisLiked(!isLiked); Bookmarked(isLiked); }; const Bookmarked = () => { return isLiked ? <RiBookmarkFill /> : <RiBookmarkLine />; }; return ( <> {props.characters.map((character, index) => ( <div className="card-container" key={index}> <img src={`${character.thumbnail.path}/standard_fantastic.${character.thumbnail.extension}`} alt="character" className="image" /> <div className="info-container"> <p className="name">{character.name}</p> <div className="icon" onClick={() => { setToggle(!toggle); handleBookmarking(character); }} > <Bookmarked /> </div> </div> </div> ))} </> ); }; export default CharactersList;El problema está en el estado en el que tienes razón. Está almacenando un valor booleano para todos sus héroes. Debe cambiar el valor del estado a una matriz de ID en lugar de un booleano y en esta matriz, almacena ID de caracteres marcados. Entonces su función handleBookmarking debería ser algo como esto:
const handleBookmarking = (character) => { if (isLiked.includes(character.id)) { const newIsLiked = [...isLiked]; newIsLiked.filter(id => id === character.id); setIsLiked(newIsLiked); } else { setIsLiked([...isLiked, character.id]); } }Con esta implementación, ya no necesita alternar el estado. Si la identificación de tu personaje está en la matriz, está marcada y si no lo está, no está marcada. Si tu personaje no tiene una identificación, puedes usar el nombre o cualquier otro accesorio que sea único. También tendrá que cambiar la implementación de su componente BookMarked a algo como esto:
//implementation of BookMarked const Bookmarked = ({id}) => { return isLiked.includes(id) ? <RiBookmarkFill /> : <RiBookmarkLine />; };Y también cámbielo en la declaración de devolución:
//from this: <Bookmarked /> //to this: <Bookmarked id={character.id} />