React Context中页面刷新后LocalStorage无法保留数据问题
问题修复:React Context 同步LocalStorage刷新后丢失数据
核心错误分析
useState 初始化方式错误
你把初始化函数放在了useState的第二个参数位置,这是不对的。useState如果需要函数式初始化(比如从LocalStorage读值),应该把这个函数直接作为第一个参数传入,否则初始值永远是空数组[],刷新后自然读不到LocalStorage里的数据。updatePokemons 中删除操作无效
slice()方法不会修改原数组,只会返回截取后的新数组,所以你执行updatedPokemons.slice(pokemonsIndex, 1)后,updatedPokemons本身根本没变化,删除操作等于没执行。deletePokemon 函数的多处错误
- 直接修改state数组
pokemons.splice(...)违反React的不可变原则,必须通过setPokemons更新状态; splice的参数不正确,删除单个元素需要传index, 1,只传index会删除从该位置到数组末尾的所有元素;- 没必要加
async/await,splice是同步操作,没有异步逻辑; toString(name)多余,若传入的name已经是字符串,这步完全没必要,若不是应该提前处理类型。
- 直接修改state数组
修复后的完整代码
import React, { useEffect, useState } from "react"; import CatchContext from "./Context"; const CatchProvider = ({ children }) => { // 修复:用函数式初始化作为useState的第一个参数 const [pokemons, setPokemons] = useState(() => { const dataStorage = localStorage.getItem('pokemons'); return dataStorage ? JSON.parse(dataStorage) : []; }); useEffect(() => { localStorage.setItem('pokemons', JSON.stringify(pokemons)); }, [pokemons]); const updatePokemons = (name) => { const pokemonsIndex = pokemons.indexOf(name); if (pokemonsIndex >= 0) { // 修复:用filter创建新数组(更符合不可变原则),替代slice setPokemons(prev => prev.filter(p => p !== name)); } else { // 用函数式更新,避免依赖外部state的快照 setPokemons(prev => [...prev, name]); } } const deletePokemon = (name) => { // 修复:用filter创建新数组,通过setPokemons更新 setPokemons(prev => prev.filter(p => p !== name)); } return ( <CatchContext.Provider value={{ pokemons, updatePokemons, deletePokemon }}> {children} </CatchContext.Provider> ); } export default CatchProvider;
额外优化点
- 在
updatePokemons和deletePokemon中使用函数式更新(setPokemons(prev => ...)),可以避免因为闭包问题导致的state快照过期,确保每次更新都基于最新的state值。 - 用
filter替代splice来删除元素,更符合React的不可变数据原则,代码也更简洁。
内容的提问来源于stack exchange,提问作者Routfin
相关产品推荐
相关产品推荐

