首頁  >  問答  >  主體

如何不可變地更新陣列並將其儲存在 React 的本機儲存中?

我正在製作一個食譜應用程式。我希望用戶能夠將食譜添加到收藏夾清單中。涉及 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粉604669414P粉604669414182 天前318

全部回覆(1)我來回復

  • P粉054616867

    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。

    回覆
    0
  • 取消回覆