我正在製作一個食譜應用程式。我希望用戶能夠將食譜添加到收藏夾清單中。涉及 3 個 React 元件。食譜、添加到收藏夾和收藏夾。
配方組件顯示有關所選配方的各種詳細資訊。
AddToFavorites 元件是一個在 Recipe 元件中呈現的按鈕。
收藏夾元件是一個列表,顯示使用「新增到收藏夾」按鈕新增到收藏夾的所有項目。
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> ) }
到目前為止我嘗試要做的事情:
當我將一項新增至收藏夾時,我可以新增一項,也可以新增多次。但是當我轉到新食譜添加另一個項目時,它會刪除舊項目並重新啟動。
幾天來我一直在研究它並嘗試不同的事情,但我無法弄清楚。
P粉0546168672024-04-03 09:03:17
這似乎是共享狀態的一個很好的例子。如果您的收藏夾資料在一個位置進行管理,那麼在新增、刪除或顯示時就不會遇到同步問題。
我建議建立一個上下文
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);
然後用上下文提供者包裝應用程式的相關部分,例如
只要您需要讀取或修改收藏,請使用上下文掛鉤
// read const { favorites } = useFavorites(); // modify const { isFavorite, toggleFavorite } = useFavorites();
您也可以使用任何其他形式的狀態管理,例如 Redux。