提问人:Neelam 提问时间:11/9/2023 更新时间:11/9/2023 访问量:8
添加所有书签,而不仅仅是更改当前状态
Add all bookmarks, instead of just changing current state
问:
我知道我只是在更改当前的书签状态,相反,我需要使用新书签更新状态,但我不确定如何这样做,或者如何通过单击按钮打开和关闭状态。
// 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;
答: 暂无答案
评论