React页面重载后LocalStorage存在键但值丢失问题
问题原因及解决方案
核心问题
你把localStorage.setItem("data", JSON.stringify(formValues))直接写在了JSX的渲染分支里,这会导致每次组件渲染(包括页面重载后)都会执行这行代码。页面重载时,formValues初始值是空对象{username:"", password: ""},所以会把LocalStorage里原来的有效数据覆盖成空值,最终表现为键存在但值丢失。
另外,isSubmit的初始状态判断会在页面重载时,如果LocalStorage有数据就设为true,直接进入成功渲染分支,触发上述的覆盖操作。
修复步骤
将LocalStorage存储逻辑移到表单提交验证通过后
修改handleSubmit函数,只有当验证无错误时,再存入LocalStorage并设置isSubmit为true:const handleSubmit = (e) => { e.preventDefault(); const errors = validate(formValues); setFormErrors(errors); // 验证通过才执行存储和提交状态设置 if (Object.keys(errors).length === 0) { localStorage.setItem("data", JSON.stringify(formValues)); setIsSubmit(true); } };从LocalStorage初始化表单数据(可选,优化体验)
页面重载时,从LocalStorage读取已存储的数据来初始化formValues,避免表单回到空状态:const initialValues = JSON.parse(localStorage.getItem("data")) || { username:"", password: "" }; const [formValues, setFormValues] = useState(initialValues);移除JSX中的存储代码
删掉成功分支里的{localStorage.setItem("data", JSON.stringify(formValues))},这行代码是问题根源。
修复后的完整代码
import { useState } from "react"; function App() { // 从LocalStorage读取初始值,没有则用空对象 const initialValues = JSON.parse(localStorage.getItem("data")) || { username:"", password: "" }; const [formValues, setFormValues] = useState(initialValues); const [formErrors, setFormErrors] = useState({}); const [isSubmit, setIsSubmit] = useState( JSON.parse(localStorage.getItem("data")) ? true : false ); const handleChange = (e) => { const { name, value } = e.target; setFormValues({ ...formValues, [name]: value }); }; const handleSubmit = (e) => { e.preventDefault(); const errors = validate(formValues); setFormErrors(errors); // 验证通过才存储并设置提交状态 if (Object.keys(errors).length === 0) { localStorage.setItem("data", JSON.stringify(formValues)); setIsSubmit(true); } }; const validate = (values) => { const errors = {}; if (!values.username) { errors.username = "Username is required!"; } if (!values.password) { errors.password = "Password is required"; } else if (values.password.length < 4) { errors.password = "Password must be more than 4 characters"; } else if (values.password.length > 8) { errors.password = "Password cannot exceed more than 10 characters"; } return errors; }; const logout = () => { setIsSubmit(false); localStorage.clear(); // 登出后重置表单值 setFormValues({ username:"", password: "" }); }; return ( <div className="container"> {Object.keys(formErrors).length === 0 && isSubmit ? ( <> <div> hello {JSON.parse(localStorage.getItem("data")).username} ,Signed in successfully </div> <button onClick={logout}>LOG OUT</button> </> ) : ( <form onSubmit={handleSubmit}> <div> <div> <label>Username</label> <input type="text" name="username" placeholder="Username" value={formValues.username} onChange={handleChange} /> </div> <p>{formErrors.username}</p> <div> <label>Password</label> <input type="password" name="password" placeholder="Password" value={formValues.password} onChange={handleChange} /> </div> <p>{formErrors.password}</p> <button>Submit</button> </div> </form> )} </div> ); } export default App;
内容的提问来源于stack exchange,提问作者kiran
相关产品推荐
相关产品推荐

