How to immutably update an array and store it in local storage in React?
P粉604669414
P粉604669414 2024-04-02 09:51:18
0
1
260

I'm making a recipe app. I want the user to be able to add recipes to a favorites list. There are 3 React components involved. Recipes, add to favorites and favorites.

The Recipe component displays various details about the selected recipe.

The AddToFavorites component is a button rendered in the Recipe component.

The Favorites component is a list that displays all items added to Favorites using the "Add to Favorites" button.

function Favorites() { const [favList, setFavList] = useState(localStorage.getItem('favorites')); return (  {favList} {favList.map(listItem => { 
  • {listItem}
  • })}
    ) }
    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 (  

    {details.title}

    {activeTab === 'instructions' && (

    )} {activeTab === 'ingredients' && (
      {details.extendedIngredients && details.extendedIngredients.map((ingredient) => (
    • {ingredient.original}
    • ))}
    )} {activeTab === 'summary' && (

    )}
    ) }
    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 (  {!active ? 'Add to favorites' : 'Remove from favorites'} 
    ) }

    What I've tried to do so far:

    • Pass API data to AddToFavorites as the "details" attribute in the Recipe.
    • Set favorites in AddToFavorites to the default empty array state.
    • Add onClick event in AddToFavorites to add to favorites btn, which calls the AddToFavorites() function.
    • In the AddToFavorites() function I try to permanently update the favorites status by using the spread operator and adding the received details prop (with API data) as a new item to a new copy of the status array and then Store it in local storage.

    When I add an item to favorites, I can add one item or multiple times. But when I go to a new recipe and add another item, it deletes the old item and restarts.

    I've been looking into it for a few days and trying different things but I can't figure it out.

    P粉604669414
    P粉604669414

    reply all (1)
    P粉054616867

    This seems to be a good example of shared state. If yourFavoritesdata is managed in one place, you won't have synchronization issues when adding, deleting or displaying it.

    I recommend creating a context

    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);

    Then wrap the relevant parts of the application with a context provider, e.g.

               
                
               

    Use context hookswhenever you need to read or modifyFavorites

    // read const { favorites } = useFavorites(); // modify const { isFavorite, toggleFavorite } = useFavorites();

    You can also use any other form of state management, such as Redux.

      Latest Downloads
      More>
      Web Effects
      Website Source Code
      Website Materials
      Front End Template
      About us Disclaimer Sitemap
      php.cn:Public welfare online PHP training,Help PHP learners grow quickly!