为何刷新页面时localStorage的PET值会变为空字符串?
问题原因及解决方案
你的代码出现刷新后localStorage的PET值变为空字符串的问题,核心原因是组件挂载时的执行顺序导致的覆盖问题:
- 组件初始化时,
petName的初始值是空字符串"" - 第二个
useEffect依赖petName,会在组件挂载时立即执行,将localStorage的PET值设置为空字符串 - 随后第一个
useEffect才执行,此时读取到的localStorage已经是空值,无法恢复之前存储的内容
最优解决方案:直接从localStorage初始化state
不需要额外的useEffect读取数据,直接在useState中初始化时获取localStorage的值,这样能避免挂载时的覆盖问题,代码更简洁高效:
import { useState, useEffect } from "react"; import petImage from "../assets/kungfudie.gif"; function App(): JSX.Element { // 直接从localStorage初始化state const [petName, setPetName] = useState<string>(() => { const storedName = localStorage.getItem("PET"); return storedName ? JSON.parse(storedName) : ""; }); // 当petName变化时更新localStorage(此时不会在初始空值时触发覆盖) useEffect(() => { localStorage.setItem("PET", JSON.stringify(petName)); }, [petName]); return ( <div className="bg-gray-900 text-gray-100 text-center p-5"> <h1 className="mb-5">My Pet</h1> <input placeholder="Set Pet Name" value={petName} type="text" name="petName" id="petName" onChange={(e) => setPetName(e.target.value)} /> <h1 className="my-5"> {petName.length > 0 ? `Hi I'm ${petName}` : "Give me a name"} </h1> <div> <img style={{ maxWidth: 500 }} src={petImage} alt="Pet Image" /> </div> </div> ); } export default App;
备选方案:给第二个useEffect添加条件判断
如果不想修改state初始化方式,可以在第二个useEffect中添加判断,避免初始空值覆盖localStorage:
useEffect(() => { // 仅当petName非空时更新localStorage if (petName) { localStorage.setItem("PET", JSON.stringify(petName)); } }, [petName]);
这种方式需要注意:如果用户主动清空输入框,localStorage不会被更新为空,会保留之前的值。如果需要支持清空功能,可以调整判断逻辑,比如添加一个状态标记组件是否完成初始化,仅在初始化完成后处理空值更新。
内容的提问来源于stack exchange,提问作者lance2k
相关产品推荐
相关产品推荐

