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

如何在React应用中使用useEffect操作localStorage实现待办数据持久化

React TodoList localStorage持久化实现方案

你当前的存储逻辑已经完成了「数据变更时写入localStorage」的部分,缺少初始化读取本地存储的逻辑,同时存在状态突变的问题,按以下步骤修改即可:


核心改动点

  • 修正任务列表状态更新逻辑:避免直接修改原数组,返回新数组触发React重渲染,同时唤醒useEffect的存储逻辑
  • 为待办列表状态添加初始化读取逻辑,从localStorage拉取上次存储的数据
  • 补充异常容错,避免非法本地数据导致页面崩溃

完整修改后代码

import React, { useState, useEffect } from 'react';
import trashIcon from './trash.svg';

function App() {
  const [taskInput, updateTaskInput] = useState('');
  // 改动1:初始化时从localStorage读取存储的待办列表
  const [toDolist, updateToDoList] = useState(() => {
    try {
      const savedLists = localStorage.getItem('lists');
      return savedLists ? JSON.parse(savedLists) : [];
    } catch (err) {
      console.warn('本地待办数据损坏,已重置', err);
      return [];
    }
  });

  const inputKeyDown = (event) => {
    if (event.keyCode === 13) addNote();
  };

  // 改动2:修正状态更新方式,不直接修改原数组
  const addNote = () => {
    if (!taskInput.trim()) return; // 新增空任务拦截
    const newTodoList = [...toDolist, { description: taskInput, isComplete: false }];
    updateToDoList(newTodoList);
    updateTaskInput('');
  };

  // 补充缺失的标记完成/删除任务逻辑,同样采用新数组更新
  const mark = (index) => {
    const newTodoList = toDolist.map((item, i) => 
      i === index ? {...item, isComplete: !item.isComplete} : item
    );
    updateToDoList(newTodoList);
  };

  const deleteTask = (index) => {
    const newTodoList = toDolist.filter((_, i) => i !== index);
    updateToDoList(newTodoList);
  };

  // 该存储逻辑无需修改,依赖toDolist变更自动写入本地
  useEffect(() => {
    localStorage.setItem('lists', JSON.stringify(toDolist));
  }, [toDolist]);

  return (
    <div className='app-background'>
      <p className=' heading-text'> To do List</p>
      <div className='task-container'>
        <div>
          <input
            className='text-input'
            value={taskInput}
            onKeyDown={inputKeyDown}
            onChange={(event) => updateTaskInput(event.target.value)}
          />
          <button className='add-button' onClick={addNote}>
            ADD
          </button>
        </div>
        {toDolist?.length ? (
          toDolist.map((toDoObject, index) => (
            <ListItem
              key={index}
              index={index}
              itemData={toDoObject}
              deleteTask={deleteTask}
              mark={mark}
            />
          ))
        ) : (
          <p className='no-item-text'>📌 No Task added</p>
        )}
      </div>

      <p className='footer-text'>Sabar_I ❤️</p>
    </div>
  );
}

function ListItem(props) {
  return (
    <div className='list-item row jc-space-between'>
      <span
        className={props.itemData.isComplete ? 'task-complete' : ''}
        onClick={() => props.mark(props.index)}
      >
        {props.itemData.isComplete ? `✅ ` : ''}&nbsp;
        {props.itemData?.description}
      </span>
      <img
        src={trashIcon}
        className='delete-icon'
        onClick={() => props.deleteTask(props.index)}
        alt='/'
      />
    </div>
  );
}

export default App;

验证方式

添加测试任务后刷新页面,已添加的任务不会消失即代表本地存储逻辑生效。

内容的提问来源于stack exchange,提问作者K S Sabarinathan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 06:36:05