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

React页面重载后localStorage存储的笔记无法持久化问题

问题排查与解决:React localStorage 页面重载后数据丢失

问题原因

  1. 循环覆盖逻辑:第二个useEffect把savedNotes设为依赖项,组件初始化时savedNotes初始值为空数组,触发该effect读取localStorage数据并更新状态;但状态更新会立即触发第一个依赖savedNotes的effect,把空数组重新写入localStorage,直接覆盖之前保存的有效数据。
  2. 初始状态未正确初始化:savedNotes初始值硬设为空数组,没有直接从localStorage读取数据,导致组件挂载时初始状态错误,引发后续存储逻辑异常。

解决方法

  1. 从localStorage直接初始化状态:在useState初始化阶段,优先读取localStorage中的数据作为初始值,避免依赖后续effect异步加载。
  2. 移除错误的监听effect:删除第二个监听savedNotes的useEffect,避免循环触发存储操作。
  3. 保留实时存储逻辑:第一个useEffect监听savedNotes变化,实时将数据写入localStorage即可。

修改后的完整代码

import { useState, useEffect } from 'react'
import { v4 as uuidv4 } from 'uuid';

function App() {
  const [count, setCount] = useState(0)
  const defaulttext = "Add a task...";
  const [inputtext, setinputtext] = useState(defaulttext)  
  const [note, setnote] = useState("")
  // 直接从localStorage读取初始值,不存在则设为空数组
  const [savedNotes, setSavedNotes] = useState(() => {
    const saved = localStorage.getItem('sNotes');
    return saved ? JSON.parse(saved) : [];
  });

  // 监听savedNotes变化,实时存储到localStorage
  useEffect(() => {
    localStorage.setItem('sNotes', JSON.stringify(savedNotes))
  }, [savedNotes])

  const handlechange = (e)=>{
    setinputtext(e.target.value) 
  }

  const handlefocus = ()=>{
    if(inputtext === defaulttext){
      setinputtext('')
    }
  }

  const savenote = () => {
    const newNote = {
      id: uuidv4(),
      text: inputtext
    };
    setSavedNotes([...savedNotes, newNote]);
    setinputtext(defaulttext);
  };
 
  useEffect(() => {
    console.log(note);
  }, [note]);

  return (
    <>
      <div className='containerr flex flex-col w-[35%] justify-center '>
        <div className="navbar bg-green-600 flex flex-row w-[100%] justify-between">
          <span>Todo List</span>
          <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" className="lucide lucide-menu"><line x1="4" x2="20" y1="12" y2="12" /><line x1="4" x2="20" y1="6" y2="6" /><line x1="4" x2="20" y1="18" y2="18" /></svg>
        </div>
        <div className='inputtext  justify-self-center ml-10 mt-4 mb-4 mr-10   flex flex-row '>
          <input onChange={handlechange} onFocus={handlefocus} type="text" value={inputtext} className=' bg-green-300 w-full outline-none ' />
          <svg onClick={savenote} xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="current" stroke="black" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="lucide lucide-plus bg-green-300 w-[23px]"><path d="M5 12h14" /><path d="M12 5v14" /></svg>
        </div>
        <div className='mynotes flex flex-col bg-green-500 min-h-[400px] text-center text-xl'> 
          <span className='bg-green-950  text-white p-3'>MyNotes</span>
          {savedNotes.length === 0 ? (
            <div>No notes yet, add one!</div>
          ) : (
            <div>
              {savedNotes.map((savednote)=>(
                <div key={savednote.id} className="note bg-green-200 mt-3 mb-3">{savednote.text}</div>
              ))}
            </div>
          )}
        </div>
      </div>
    </>
  )
}

export default App

额外优化:将原有的"Loading..."提示改为更贴合场景的"No notes yet, add one!",因为初始状态已直接从localStorage读取,不存在异步加载过程。

内容的提问来源于stack exchange,提问作者Papayc

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 13:06:00