添加所有书签,而不仅仅是更改当前状态

Add all bookmarks, instead of just changing current state

提问人:Neelam 提问时间:11/9/2023 更新时间:11/9/2023 访问量:8

问:

我知道我只是在更改当前的书签状态,相反,我需要使用新书签更新状态,但我不确定如何这样做,或者如何通过单击按钮打开和关闭状态。

// MyBookmarksContext.tsx

import {
  ReactNode,
  createContext,
  useContext,
  useState,
  useEffect,
} from "react";

type MyBookmarksProviderProps = {
  children: ReactNode;
};

interface MyBookmark {
  userId: string | null;
  status: boolean;
  id: number;
  title: string;
  image: string;
  servings: number;
  readyInMinutes: number;
  dairyFree: boolean;
  glutenFree: boolean;
  ketogenic: boolean;
  vegan: boolean;
  vegetarian: boolean;
  extendedIngredients: {
    original: string;
    id: string;
  }[];
  steps: {
    number: number;
    step: string;
  }[];
}

type MyBookmarkContextType = {
  bookmarks: MyBookmark[];
  toggleBookmark: (bookmark: MyBookmark) => void;
  deleteBookmark: (bookmarkId: number) => void;
  isBookmarked: boolean;
};

export const MyBookmarksContext = createContext<MyBookmarkContextType | null>(
  null
);

export const MyBookmarksProvider = ({ children }: MyBookmarksProviderProps) => {
  const [bookmarks, setBookmarks] = useState<MyBookmark[]>([]);

  const [isBookmarked, setIsBookmarked] = useState<boolean>(false);

  useEffect(() => {
    const savedBookmarks = JSON.parse(localStorage.getItem("bookmark") || "[]");
    setBookmarks(savedBookmarks);
  }, []);

  useEffect(() => {
    localStorage.setItem("bookmark", JSON.stringify(bookmarks));
  }, [bookmarks]);

  const toggleBookmark = (bookmark: MyBookmark) => {
    setBookmarks([
      {
        userId: bookmark.userId,
        status: bookmark.status,
        id: bookmark.id,
        title: bookmark.title,
        image: bookmark.image,
        servings: bookmark.servings,
        readyInMinutes: bookmark.readyInMinutes,
        dairyFree: bookmark.dairyFree,
        glutenFree: bookmark.glutenFree,
        ketogenic: bookmark.ketogenic,
        vegan: bookmark.vegan,
        vegetarian: bookmark.vegetarian,
        extendedIngredients: bookmark.extendedIngredients.map(
          (ing: { original: string; id: string }) => ({
            original: ing.original,
            id: ing.id,
          })
        ),
        steps: bookmark.steps.map((inst: { number: number; step: string }) => ({
          number: inst.number,
          step: inst.step,
        })),
      },
    ]);
  };

  const deleteBookmark = () => {
    console.log("delete bookmark");
  };

  return (
    <MyBookmarksContext.Provider
      value={{ bookmarks, toggleBookmark, deleteBookmark, isBookmarked }}
    >
      {children}
    </MyBookmarksContext.Provider>
  );
};

export const useMyBookmarkContext = () => {
  const context = useContext(MyBookmarksContext);
  if (!context) {
    throw new Error(
      "useBookmarkContext must be used within a BookmarkProvider"
    );
  }
  return context;
};

在这里,我将尝试控制切换按钮,但现在我只是尝试添加新书签,而不仅仅是更改当前状态。!我注释掉了相关部分!

// RecipeLayout.tsx

const RecipeLayout = (): JSX.Element => {

  const { bookmarks, toggleBookmark, deleteBookmark, isBookmarked } =
    useMyBookmarkContext();

  const navigate = useNavigate();

  const recipeStorage = JSON.parse(localStorage.getItem("recipe") || "{}");

  const recipe = {
    id: recipeStorage[0].id,
    title: recipeStorage[0].title,
    image: recipeStorage[0].image,
    servings: recipeStorage[0].servings,
    readyInMinutes: recipeStorage[0].readyInMinutes,
    dairyFree: recipeStorage[0].dairyFree,
    glutenFree: recipeStorage[0].glutenFree,
    ketogenic: recipeStorage[0].ketogenic,
    vegan: recipeStorage[0].vegan,
    vegetarian: recipeStorage[0].vegetarian,
    extendedIngredients: recipeStorage[0].extendedIngredients.map(
      (ing: { original: string; id: string }) => ({
        original: ing.original,
        id: ing.id,
      })
    ),
  };

  const recipeInstructionsStorage = JSON.parse(
    localStorage.getItem("recipeInstructions") || "{}"
  );
  const recipeInstructions = {
    steps: recipeInstructionsStorage[0].steps.map(
      (inst: { number: number; step: string }) => ({
        number: inst.number,
        step: inst.step,
      })
    ),
  };

 /////////////////////////////////////////// RELEVANT PART 1/2 ///////////////////////////////   
  const bookmarkUserAccess = () => {
    const user = auth.currentUser;
    if (user) {
      toggleBookmark({
        userId: user.email,
        status: true,
        id: recipe.id,
        title: recipe.title,
        image: recipe.image,
        servings: recipe.servings,
        readyInMinutes: recipe.readyInMinutes,
        dairyFree: recipe.dairyFree,
        glutenFree: recipe.glutenFree,
        ketogenic: recipe.ketogenic,
        vegan: recipe.vegan,
        vegetarian: recipe.vegetarian,
        extendedIngredients: recipe.extendedIngredients.map(
          (ing: { original: string; id: string }) => ({
            original: ing.original,
            id: ing.id,
          })
        ),
        steps: recipeInstructions.steps.map(
          (inst: { number: number; step: string }) => ({
            number: inst.number,
            step: inst.step,
          })
        ),
      });
      console.log(bookmarks);
    } else {
      navigate("/login");
    }
  };

////////////////////////////////////////////////////////////////////////////////////////
  return (
    <main className={styles["recipe-container"]}>
      <section className={styles.box}>
        <div className={styles["image-container"]}>
          <div className={styles["image-wrapper"]}></div>
          <img
            src={recipe.image}
            className={styles["recipe-image"]}
            alt="Food"
          />
        </div>

        <div className={styles["ingredients-container"]}>
          <h2 className={styles["ingredients-header"]}>ingredients</h2>
          <ul className={styles["ingredients-list"]}>
            {recipe.extendedIngredients.map(
              (ing: { original: string; id: string }) => (
                <li key={ing.id} className={styles["ingredients-list-item"]}>
                  {ing.original}
                </li>
              )
            )}
          </ul>
        </div>
        <div className={styles["recipe-data-container"]}>
          <div className={styles["recipe-header"]}>
            <h1 className={styles["recipe-name"]}>{recipe.title}</h1>
            <ul className={styles.extras}>
              <li className={styles["extras-list-item"]}>
                <div className={styles.servings}>
                  <i className="fa-solid fa-user"></i>
                </div>
                <p className={styles.text}>{recipe.servings}</p>
              </li>
              <li className={styles["extras-list-item"]}>
                <div className={styles.duration}>
                  <i className="fa-solid fa-clock"></i>
                </div>
                <p className={styles.text}>{recipe.readyInMinutes}mins</p>
              </li>
            </ul>
          </div>
///////////////////////////////// RELEVANT PART 2/2 ///////////////////////////////////////
          <div
            className={styles["bookmarks-container"]}
            onClick={bookmarkUserAccess}
          >
          
            <i className="fa-regular fa-bookmark"></i>
          </div>
//////////////////////////////////////////////////////////////////////////////////////////////
          <div className={styles["steps-container"]}>
            <ul className={styles["steps-list"]}>
              {recipeInstructions.steps.map(
                (instr: { number: number; step: string }) => (
                  <li key={instr.number} className={styles["steps-list-item"]}>
                    <h2 className={styles["step-heading"]}>
                      Step <span className={styles.count}>{instr.number}</span>
                    </h2>
                    <p className={styles.instruction}>{instr.step}</p>
                  </li>
                )
              )}
            </ul>
          </div>
        </div>
        <div className={styles["source-contents-container"]}>
          <ul className={styles["source-contents-list"]}>
            <li className={styles["source-contents-list-item"]}>
              <div className={styles.check}>
                {recipe.dairyFree ? (
                  <div className={styles.checkmark}>
                    <i className="fa-solid fa-circle-check"></i>
                  </div>
                ) : (
                  <div className={styles.xmark}>
                    <i className="fa-solid fa-circle-xmark"></i>
                  </div>
                )}
              </div>
              <p className={styles.text}>dairy free</p>
            </li>
            <li className={styles["source-contents-list-item"]}>
              <div className={styles.check}>
                {recipe.glutenFree ? (
                  <div className={styles.checkmark}>
                    <i className="fa-solid fa-circle-check"></i>
                  </div>
                ) : (
                  <div className={styles.xmark}>
                    <i className="fa-solid fa-circle-xmark"></i>
                  </div>
                )}
              </div>
              <p className={styles.text}>gluten free</p>
            </li>
            <li className={styles["source-contents-list-item"]}>
              <div className={styles.check}>
                {recipe.ketogenic ? (
                  <div className={styles.checkmark}>
                    <i className="fa-solid fa-circle-check"></i>
                  </div>
                ) : (
                  <div className={styles.xmark}>
                    <i className="fa-solid fa-circle-xmark"></i>
                  </div>
                )}
              </div>
              <p className={styles.text}>ketogenic</p>
            </li>
            <li className={styles["source-contents-list-item"]}>
              <div className={styles.check}>
                {recipe.vegan ? (
                  <div className={styles.checkmark}>
                    <i className="fa-solid fa-circle-check"></i>
                  </div>
                ) : (
                  <div className={styles.xmark}>
                    <i className="fa-solid fa-circle-xmark"></i>
                  </div>
                )}
              </div>
              <p className={styles.text}>vegan</p>
            </li>
            <li className={styles["source-contents-list-item"]}>
              <div className={styles.check}>
                {recipe.vegetarian ? (
                  <div className={styles.checkmark}>
                    <i className="fa-solid fa-circle-check"></i>
                  </div>
                ) : (
                  <div className={styles.xmark}>
                    <i className="fa-solid fa-circle-xmark"></i>
                  </div>
                )}
              </div>
              <p className={styles.text}>vegetarian</p>
            </li>
          </ul>
        </div>
      </section>
    </main>
  );
};

export default RecipeLayout;
reactjs typescript 本地存储 react-context

评论


答: 暂无答案