Wie aktualisiere ich ein Array unveränderlich und speichere es im lokalen Speicher in React?
P粉604669414
P粉604669414 2024-04-02 09:51:18
0
1
439

Ich mache eine Rezept-App. Ich möchte, dass der Benutzer Rezepte zu einer Favoritenliste hinzufügen kann. Es sind 3 React-Komponenten beteiligt. Rezepte, zu Favoriten und Favoriten hinzufügen.

Recipe-Komponente zeigt verschiedene Details zum ausgewählten Rezept an.

Die AddToFavorites-Komponente ist eine Schaltfläche, die innerhalb der Recipe-Komponente gerendert wird.

Die Komponente „Favoriten“ ist eine Liste, die alle Elemente anzeigt, die über die Schaltfläche „Zu Favoriten hinzufügen“ zu den Favoriten hinzugefügt wurden.

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

Was ich bisher versucht habe:

  • Übergeben Sie API-Daten als „Details“-Attribut im Rezept an AddToFavorites.
  • Legen Sie die Favoriten in AddToFavorites standardmäßig auf ein leeres Array fest.
  • Fügen Sie ein onClick-Ereignis in AddToFavorites hinzu, um es zu Favoriten hinzuzufügen, wodurch die Funktion AddToFavorites() aufgerufen wird.
  • In der AddToFavorites()-Funktion versuche ich, den Favoritenstatus dauerhaft zu aktualisieren, indem ich den Spread-Operator verwende und die empfangene Detail-Requisite (mit API-Daten) als neues Element zu einer neuen Kopie des Status-Arrays hinzufüge und dann im lokalen Speicher speichere.

Wenn ich einen Artikel zu meinen Favoriten hinzufüge, kann ich einen Artikel oder mehrere Male hinzufügen. Aber wenn ich zu einem neuen Rezept gehe und einen weiteren Artikel hinzufüge, wird der alte Artikel gelöscht und neu gestartet.

Ich habe ein paar Tage damit verbracht und verschiedene Dinge ausprobiert, aber ich komme nicht dahinter.

P粉604669414
P粉604669414

Antworte allen(1)
P粉054616867

这似乎是共享状态的一个很好的例子。如果您的收藏夹数据在一个位置进行管理,那么在添加、删除或显示时就不会遇到同步问题。

我建议创建一个上下文

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。

Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage