#javascript #reactjs #react-hooks #state
#язык JavaScript #реагирует на #реагируют-крючки #государство
Вопрос:
Я создаю приложение для закладок персонажей marvel (героев), поэтому, когда я нажимаю на определенный значок закладки, он должен превратиться в значок заполненной закладки и наоборот. К сожалению, когда я нажимаю на один из них, все значки меняются. Я думаю, проблема в штате. Пожалуйста, помогите!
В качестве реквизита я получаю все данные о персонажах (изображение, имя). Вот код:
import React, { useState, useEffect } from "react"; import "./CharactersList.css"; import { RiBookmarkLine } from "react-icons/ri"; import { RiBookmarkFill } from "react-icons/ri"; const CharactersList = (props) =gt; { const [isLiked, setisLiked] = useState(false); const [toggle, setToggle] = useState(false); const [favourites, setFavourites] = useState([]); useEffect(() =gt; { const bookMarkedData = JSON.parse( localStorage.getItem("react-bookmarked-characters") ); if (bookMarkedData) { setFavourites(bookMarkedData); } }, []); const saveToLocalStorage = (data) =gt; { localStorage.setItem("react-bookmarked-characters", JSON.stringify(data)); }; const handleBookmarking = (character) =gt; { if (toggle === true) { const newBookmarkedList = [...favourites, character]; setFavourites(newBookmarkedList); saveToLocalStorage(newBookmarkedList); setisLiked(true); } else { const newBookmarkedList = favourites.filter( (favourites) =gt; favourites.id !== character.id ); setFavourites(newBookmarkedList); saveToLocalStorage(newBookmarkedList); setisLiked(false); } }; const toggleLike = () =gt; { setisLiked(!isLiked); Bookmarked(isLiked); }; const Bookmarked = () =gt; { return isLiked ? lt;RiBookmarkFill /gt; : lt;RiBookmarkLine /gt;; }; return ( lt;gt; {props.characters.map((character, index) =gt; ( lt;div className="card-container" key={index}gt; lt;img src={`${character.thumbnail.path}/standard_fantastic.${character.thumbnail.extension}`} alt="character" className="image" /gt; lt;div className="info-container"gt; lt;p className="name"gt;{character.name}lt;/pgt; lt;div className="icon" onClick={() =gt; { setToggle(!toggle); handleBookmarking(character); }} gt; lt;Bookmarked /gt; lt;/divgt; lt;/divgt; lt;/divgt; ))} lt;/gt; ); }; export default CharactersList;
Ответ №1:
Проблема в том, в каком состоянии вы правы. Вы сохраняете одно логическое значение для всех ваших героев. Вы должны изменить значение состояния на массив идентификаторов вместо одного логического значения, и в этом массиве вы храните идентификаторы символов, помеченных закладками. Таким образом, ваша функция закладки руля должна быть примерно такой:
const handleBookmarking = (character) =gt; { if (isLiked.includes(character.id)) { const newIsLiked = [...isLiked]; newIsLiked.filter(id =gt; id === character.id); setIsLiked(newIsLiked); } else { setIsLiked([...isLiked, character.id]); } }
При такой реализации вам больше не нужно переключать состояние. Если идентификатор вашего персонажа находится в массиве, он помечен закладкой, а если нет, то он не помечен. Если у вашего персонажа нет идентификатора, вы можете использовать имя или любую другую уникальную опору. Вам также придется изменить реализацию компонента с закладками на что-то вроде этого:
//implementation of BookMarked const Bookmarked = ({id}) =gt; { return isLiked.includes(id) ? lt;RiBookmarkFill /gt; : lt;RiBookmarkLine /gt;; };
А также измените его в заявлении о возврате:
//from this: lt;Bookmarked /gt; //to this: lt;Bookmarked id={character.id} /gt;
Комментарии:
1. Спасибо, это работает нормально, но теперь я не могу отменить закладку своего элемента, я не знаю, как активировать отмену закладки без какого-либо переключателя… а также, когда я обновляю свой браузер, состояние значка закладки не сохраняется, поэтому похоже, что мои элементы с закладками не помечены, хотя они есть 🙁