Maison > Questions et réponses > le corps du texte
Je crée une application de recettes. Je souhaite que l'utilisateur puisse ajouter des recettes à une liste de favoris. Il y a 3 composants React impliqués. Recettes, ajouter aux favoris et favoris.
Le composant Recette affiche divers détails sur la recette sélectionnée.
Le composant AddToFavorites est un bouton rendu dans le composant Recipe.
Le composant Favoris est une liste qui affiche tous les éléments ajoutés aux Favoris à l'aide du bouton « Ajouter aux Favoris ».
function Favorites() { const [favList, setFavList] = useState(localStorage.getItem('favorites')); return ( <FavPageContainer> {favList} {favList.map(listItem => { <li>{listItem}</li> })} </FavPageContainer> ) }
function Recipe() { let params = useParams(); const [details, setDetails] = useState({}); const [activeTab, setActiveTab] = useState('summary'); const fetchDetails = async () => { const data = await fetch(`https://api.spoonacular.com/recipes/${params.name}/information?apiKey=${process.env.REACT_APP_API_KEY}`); const detailData = await data.json(); setDetails(detailData); } useEffect(() => { fetchDetails(); }, [params.name]); return ( <DetailWrapper> <h2>{details.title}</h2> <img src={details.image} alt="" /> <Info> <ButtonContainer> <AddToFavorites details={details}/> <Button className={activeTab === 'summary' ? 'active' : ''} onClick={() => setActiveTab('summary')}>Nutrition Info </Button> <Button className={activeTab === 'ingredients' ? 'active' : ''} onClick={() => setActiveTab('ingredients')}>Ingredients </Button> <Button className={activeTab === 'instructions' ? 'active' : ''} onClick={() => setActiveTab('instructions')}>Instructions </Button> </ButtonContainer> {activeTab === 'instructions' && ( <div> <p dangerouslySetInnerHTML={{__html: details.instructions}}></p> </div> )} {activeTab === 'ingredients' && ( <ul> {details.extendedIngredients && details.extendedIngredients.map((ingredient) => ( <li key={ingredient.id}> {ingredient.original}</li> ))} </ul> )} {activeTab === 'summary' && ( <div> <p dangerouslySetInnerHTML={{__html: details.summary}}></p> </div> )} </Info> </DetailWrapper> ) }
function AddToFavorites(details) { const [active, setActive] = useState(false); const [favorites, setFavorites] = useState([]); const handleActive = () => { setActive(!active); }; const handleFavorites = () => { handleActive(); if(active){ removeFromFavorites(); } else if(!active) { addToFavorites(); } }; const addToFavorites = () => { handleActive(); setFavorites([...favorites, details]); console.log(favorites) localStorage.setItem('favorites', JSON.stringify(favorites)); }; return ( <AddToFavBtn className={active ? 'active' : null} onClick={handleFavorites}> {!active ? 'Add to favorites' : 'Remove from favorites'} <div> <BsFillSuitHeartFill/> </div> </AddToFavBtn> ) }
Ce que j'ai essayé jusqu'à présent :
Lorsque j'ajoute un élément aux favoris, je peux ajouter un élément ou plusieurs fois. Mais lorsque je consulte une nouvelle recette et que j'ajoute un autre élément, il supprime l'ancien élément et redémarre.
J'y réfléchis depuis quelques jours et j'ai essayé différentes choses mais je n'arrive pas à comprendre.
P粉0546168672024-04-03 09:03:17
Cela semble être un bon exemple d'état partagé. Si vos données Favoris sont gérées au même endroit, vous n'aurez pas de problèmes de synchronisation lors de l'ajout, de la suppression ou de l'affichage.
Je recommande de créer un contexte
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, } from "react"; const FavoritesContext = createContext({ favorites: [], toggleFavorite: () => {}, isFavorite: () => false, }); // default context value export const FavoritesContextProvider = ({ children }) => { const preloadRef = useRef(false); const [favorites, setFavorites] = useState( JSON.parse(localStorage.getItem("favorites")) ?? [] ); // assuming favourites have IDs const ids = useMemo( () => new Set(favorites.map(({ id }) => id)), [favorites] ); const isFavorite = useCallback((id) => ids.has(id), [ids]); // sync data on change useEffect(() => { // skip initial preload if (preloadRef.current) { localStorage.setItem("favorites", JSON.stringify(favorites)); } preloadRef.current = true; }, [favorites]); const toggleFavorite = ({ id, image, title, route }) => { if (isFavorite(id)) { setFavorites((prev) => prev.filter((fav) => fav.id !== id)); } else { setFavorites((prev) => [...prev, { id, image, title, route }]); } }; return ({children} ); }; // hook helper export const useFavorites = () => useContext(FavoritesContext);
Ensuite, enveloppez les parties pertinentes de l'application avec un fournisseur de contexte, comme
Chaque fois que vous avez besoin de lire ou de modifier des favoris, utilisez des crochets contextuels
// read const { favorites } = useFavorites(); // modify const { isFavorite, toggleFavorite } = useFavorites();
Vous pouvez également utiliser toute autre forme de gestion d'état, comme Redux.