You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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完成,不存在独立的setItems setter函数
  • 读取缓存的useEffect中声明了和外层全局状态同名的basket局部变量,存在作用域混淆风险
修复方案
  1. 首先在全局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;
  1. 修改组件中读取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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 18:15:51