React开发待办类观剧列表,页面刷新后Local Storage数据丢失如何解决?
问题根因
- 缓存读写逻辑位置完全错位
你把剧集列表的缓存读取逻辑写在了子组件MyWatchListItem里,且读出来的数据赋值给了控制编辑状态的edit变量,根本没有更新真正用来渲染列表的watchLists状态(该状态存储在父组件MyWatchList中)。 - 父组件状态初始化未读取缓存
主组件MyWatchList中watchLists的初始值直接写死为空数组,页面刷新后状态自然回到空值。 - 子组件缓存写入逻辑未加依赖,导致初始渲染直接覆盖原有缓存
MyWatchListItem中写入localStorage的useEffect没有添加依赖数组,组件第一次渲染时父组件传过来的watchLists还是初始空值,该钩子直接执行把空数组写入localStorage,之前存储的有效数据直接被清空。
修改方案
1. 调整主组件MyWatchList逻辑
将缓存读写逻辑移到存储watchLists状态的主组件中,初始化时读缓存,状态变化时写缓存:
// 新增导入useEffect import React, { useState, useEffect } from "react"; import { MyWatchListForm } from "./MyWatchListForm"; import { MyWatchListItem } from "./MyWatchListItem"; export const MyWatchList = () => { // 初始化从localStorage读数据,读不到则用空数组 const [watchLists, setWatchLists] = useState(() => { const savedData = localStorage.getItem("my-watchList"); return savedData ? JSON.parse(savedData) : []; }); // 监听watchLists变化,更新缓存 useEffect(() => { localStorage.setItem("my-watchList", JSON.stringify(watchLists)); }, [watchLists]); // 原有新增、编辑、删除、完成逻辑无需改动,直接保留即可 const addWatchList = (watchList) => { if (!watchList.text || /^\s*$/.test(watchList.text)) { return; } const newWatchList = [watchList, ...watchLists]; setWatchLists(newWatchList); }; const updateWatchList = (watchListId, newValue) => { if (!newValue.text || /^\s*$/.test(newValue.text)) { return; } setWatchLists((prev) => prev.map((item) => (item.id === watchListId ? newValue : item)) ); }; const removeWatchList = (id) => { const removeArr = [...watchLists].filter((watchList) => watchList.id !== id); setWatchLists(removeArr); }; const completeWatchList = (id) => { const updatedWatchList = watchLists.map((watchList) => { if (watchList.id === id) { watchList.isComplete = !watchList.isComplete; } return watchList; }); setWatchLists(updatedWatchList); }; return ( <div> <h1>Watch later</h1> <MyWatchListForm onSubmit={addWatchList} /> <MyWatchListItem watchLists={watchLists} completeWatchList={completeWatchList} removeWatchList={removeWatchList} updateWatchList={updateWatchList} /> </div> ); };
2. 清理子组件MyWatchListItem冗余逻辑
删掉子组件中错位的缓存读写逻辑即可:
import React, { useState } from "react"; import { RiCloseCircleLine } from "react-icons/ri"; import { TiEdit } from "react-icons/ti"; import { MyWatchListForm } from "./MyWatchListForm"; export const MyWatchListItem = ({ watchLists, completeWatchList, removeWatchList, updateWatchList, }) => { const [edit, setEdit] = useState({ id: null, value: "", }); const submitUpdate = (value) => { updateWatchList(edit.id, value); setEdit({ id: null, value: "", }); }; // 删掉原有两个操作localStorage的useEffect,冗余且逻辑错误 if (edit.id) { return <MyWatchListForm edit={edit} onSubmit={submitUpdate} />; } return watchLists.map((watchList, index) => ( <div className={watchList.isComplete ? "checked" : ""} key={index}> <div key={watchList.id} onClick={() => completeWatchList(watchList.id)}> {watchList.text} </div> <div> <RiCloseCircleLine onClick={() => removeWatchList(watchList.id)} /> <TiEdit onClick={() => setEdit({ id: watchList.id, value: watchList.text })} /> </div> </div> )); };
3. 补充MyWatchListForm的缺失依赖
你的表单组件漏了React钩子的导入,同时自动聚焦的useEffect要加空依赖避免重复执行:
// 顶部新增导入 import React, { useState, useRef, useEffect } from "react"; export const MyWatchListForm = (props) => { const [input, setInput] = useState(props.edit ? props.edit.value : ""); const inputRef = useRef(); // 加空依赖数组,只在组件挂载时执行一次聚焦 useEffect(() => { inputRef.current.focus(); }, []); // 原有提交、输入逻辑无需改动 const handleSubmit = (e) => { e.preventDefault(); props.onSubmit({ id: Math.floor(Math.random() * 10000), text: input, }); setInput(""); }; const handleChange = (e) => { setInput(e.target.value); }; return ( <form className="w-full max-w-sm flex items-center border-b border-teal-500 py-2" onSubmit={handleSubmit} > {props.edit ? ( <> <input className="appearance-none bg-transparent border-none w-full text-gray-700 mr-3 py-1 px-2 leading-tight focus:outline-none" type="text" value={input} placeholder="Update the episode" onChange={handleChange} ref={inputRef} ></input> <button>Update</button> </> ) : ( <> <input className="appearance-none bg-transparent border-none w-full text-gray-700 mr-3 py-1 px-2 leading-tight focus:outline-none" type="text" value={input} placeholder="Add the episode" onChange={handleChange} ref={inputRef} ></input> <button>Add</button> </> )} </form> ); };
内容的提问来源于stack exchange,提问作者Alice378
相关产品推荐
相关产品推荐

