React食谱应用星级评分本地存储失效问题求助
解决食谱应用评分无法存入localStorage的问题
问题根源分析
你的代码存在几个关键问题导致评分无法存入localStorage:
- 误用
useCallback处理副作用:useCallback是用来缓存函数的,不是执行存储这类副作用的,应该用useEffect。 - 未解析localStorage的字符串数据:从
localStorage.getItem拿到的是JSON字符串,直接给它加属性不会生效,必须转成对象。 - 缺失React钩子导入:代码里用了
useState、useEffect但没导入,会引发运行错误。 - 依赖项不全:存储逻辑依赖
details.id,但之前的依赖数组没加,初始时details是空对象,id不存在会导致存储键错误。 - 未读取已有评分:组件挂载时没从localStorage加载之前的评分,无法恢复用户历史评分。
修正后的完整代码
import styled from "styled-components"; import Searched from "../Pages/Searched"; import { useParams, useState, useEffect } from "react"; // 补充React钩子导入 const StarRating = () => { let params = useParams(); const [details, setDetails] = useState({}); const [activeTab, setActiveTab] = useState("instructions"); const [rating, setRating] = useState(0); const [hover, setHover] = useState(0); 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]); // 组件挂载后读取已有评分 useEffect(() => { if (details.id) { const storedRatings = JSON.parse(localStorage.getItem("rating")) || {}; if (storedRatings[details.id]) { setRating(storedRatings[details.id]); } } }, [details.id]); // 评分变化时更新localStorage useEffect(() => { if (details.id) { const storedRatings = JSON.parse(localStorage.getItem("rating")) || {}; storedRatings[details.id] = rating; localStorage.setItem("rating", JSON.stringify(storedRatings)); } }, [rating, details.id]); return ( <StarStyle> <div className="star-rating"> {[...Array(5)].map((star, index) => { index += 1; return ( <button type="button" key={index} className={index <= (hover || rating) ? "on" : "off"} onClick={() => setRating(index)} onMouseEnter={() => setHover(index)} onMouseLeave={() => setHover(rating)} > <span className="star">★</span> </button> ); })} </div> </StarStyle> ); }; export default StarRating; const StarStyle = styled.form` button { background-color: transparent; border: none; outline: none; cursor: pointer; block-size: 150px; font-size: 60px; } .on { color: #000; } .off { color: #ccc; } `;
关键修改说明
- 替换useCallback为useEffect:用
useEffect处理存储和读取的副作用,符合React的副作用处理规范。 - 解析localStorage数据:每次读取
rating时用JSON.parse转成对象,修改后用JSON.stringify存回,确保数据格式正确。 - 补充钩子导入:添加
useState、useEffect的导入,避免运行时错误。 - 完善依赖数组:存储逻辑的依赖数组加入
details.id,确保只有当食谱ID存在且评分变化时才执行存储。 - 添加初始评分读取:组件挂载后,当
details.id存在时,从localStorage读取对应食谱的评分并同步到状态。 - 增加存在性判断:在存储和读取时都判断
details.id是否存在,避免初始阶段details为空对象导致的无效存储。
内容的提问来源于stack exchange,提问作者raul atofanei
相关产品推荐
相关产品推荐

