React使用localStorage时出现setItems未定义报错
问题现象
调用localStorage.setItem()写入数据时无报错、功能正常,调用getItem()读取存储对象时抛出如下ESLint校验错误:
src\components\UserCourses.js Line 33:8: 'setItems' is not defined no-undef
相关核心代码如下:
// 写入localStorage的逻辑 useEffect(() => { localStorage.setItem('basket', JSON.stringify(basket)); }, [basket]); // 读取localStorage的逻辑 useEffect(() => { const basket = JSON.parse(localStorage.getItem('basket')); if (basket) { setItems(basket); } }, []);
其中basket为定义的初始值为空数组的状态,用于存放添加的条目数据,项目采用Context+useReducer实现全局状态管理,相关上下文代码:
import { useStateValue } from './StateProvider' import {useState, useEffect} from 'react' function UserCourses ({id, name, prof, language}) { const [{basket}, dispatch] = useStateValue(); const navigate = useNavigate() const goCourseDetail = () => navigate(`/course/id=${id}`) const removeFromBasket = () => { dispatch({ type: 'REMOVE_FROM_BASKET', id: id, }); } useEffect(() => { localStorage.setItem('basket', JSON.stringify(basket)); }, [basket]); useEffect(() => { const basket = JSON.parse(localStorage.getItem('basket')); if (basket) { setItems(basket); } }, []); // 组件其余逻辑... } // StateProvider 实现 import React, {createContext, useContext, useReducer} from 'react'; export const StateContext = createContext(); export const StateProvider = ({reducer, initialState, children}) => ( <StateContext.Provider value={useReducer(reducer, initialState)}> {children} </StateContext.Provider> ); export const useStateValue = () => useContext(StateContext);
错误原因
核心问题是代码中从未定义名为setItems的状态更新方法:
- 项目使用useReducer做全局状态管理,所有状态更新都需要通过从
useStateValue解构出的dispatch方法派发action完成,不存在独立的setItemssetter函数 - 读取缓存的useEffect中声明了和外层全局状态同名的
basket局部变量,存在作用域混淆风险
修复方案
- 首先在全局reducer中新增初始化购物车状态的action处理逻辑,示例reducer代码:
// 初始状态 export const initialState = { basket: [], // 其他全局状态... }; const reducer = (state, action) => { switch(action.type) { // 已有的移除购物车逻辑 case 'REMOVE_FROM_BASKET': return { ...state, basket: state.basket.filter(item => item.id !== action.id) } // 新增:初始化购物车(同步本地缓存到全局状态) case 'SET_BASKET': return { ...state, basket: action.basket } default: return state; } } export default reducer;
- 修改组件中读取localStorage的useEffect逻辑,替换不存在的
setItems调用为dispatch派发更新,同时优化变量命名、增加异常捕获避免缓存损坏导致页面报错:
useEffect(() => { try { const storedBasket = JSON.parse(localStorage.getItem('basket')); // 校验缓存数据格式合法再更新 if (Array.isArray(storedBasket)) { dispatch({ type: 'SET_BASKET', basket: storedBasket }) } } catch (err) { console.error('读取本地购物车缓存失败,已清除损坏缓存', err); localStorage.removeItem('basket'); } }, []);
优化建议
- 避免在局部作用域声明和外层状态同名的变量,比如将读取到的缓存值命名为
storedBasket而非和全局状态同名的basket,减少作用域混淆导致的bug - 所有
JSON.parse操作建议包裹在try/catch中,避免本地存储被人为篡改、数据格式损坏时阻塞页面渲染
内容的提问来源于stack exchange,提问作者HappyJava
相关产品推荐
相关产品推荐

