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

React中useEffect使用问题:页面刷新后LocalStorage数据丢失求助

问题排查与解决方案

你的PetApp在页面刷新后数据丢失的核心问题是初始渲染时LocalStorage被空数组覆盖,具体原因和修复方案如下:

问题根源

  1. 初始state与useEffect执行顺序冲突
    你当前的代码中,pets初始化为空数组[],组件挂载后会触发两个useEffect:

    • 第一个useEffect(空依赖)尝试从LocalStorage读取数据并设置到pets,但这个操作是异步的,React会在后续渲染中更新state
    • 第二个useEffect(依赖pets)会在初始pets为空数组时立即执行,把空数组写入LocalStorage,直接覆盖了之前存储的有效数据
  2. AddPetForm的小问题(非核心但影响体验)
    表单中三个输入框的state初始值未定义(useState()),会导致输入框的value为undefined,可能引发React警告。

修复代码

import { useEffect, useState } from 'react';

function PetApp() {
  // 初始state直接从LocalStorage读取,不存在则设为空数组
  const [pets, setPets] = useState(() => {
    const saved = localStorage.getItem('examplePetData');
    return saved ? JSON.parse(saved) : [];
  });

  // 仅当pets变化时写入LocalStorage,无需担心初始覆盖
  useEffect(() => {
    localStorage.setItem('examplePetData', JSON.stringify(pets));
  }, [pets]);

  return (
    <>
      <AddPetForm setPets={setPets} />
      <ul>
        {pets.map(pet => (
          <Pet setPets={setPets} id={pet.id} name={pet.name} species={pet.species} age={pet.age} key={pet.id} />
        ))}
      </ul>
    </>
  );
}

function AddPetForm(props) {
  // 修正初始值为空字符串,避免React警告
  const [name, setName] = useState('');
  const [species, setSpecies] = useState('');
  const [age, setAge] = useState('');

  function handleSubmit(e) {
    e.preventDefault();
    props.setPets(prev => prev.concat({ name, species, age, id: Date.now() }));
    setName('');
    setSpecies('');
    setAge('');
  }

  return (
    <form onSubmit={handleSubmit}>
      <fieldset>
        <legend>添加新宠物</legend>
        <input value={name} onChange={e => setName(e.target.value)} placeholder="名字" />
        <input value={species} onChange={e => setSpecies(e.target.value)} placeholder="种类" />
        <input value={age} onChange={e => setAge(e.target.value)} placeholder="年龄(岁)" />
        <button>添加宠物</button>
      </fieldset>
    </form>
  );
}

function Pet(props) {
  function handleDelete() {
    props.setPets(prev => prev.filter(pet => pet.id !== props.id));
  }

  return (
    <li>
      {props.name} 是一只{props.species},今年{props.age}岁。
      <button onClick={handleDelete}>删除</button>
    </li>
  );
}
export default PetApp;

关键修复点说明

  • 初始state初始化:使用useState的函数式初始化,只在组件首次挂载时读取一次LocalStorage,避免重复读取,同时保证初始state就是存储的数据,不会出现空数组覆盖的情况。
  • 移除多余的读取useEffect:不再需要第一个空依赖的useEffect,因为初始state已经完成了数据读取。
  • 修正表单初始值:将表单输入框的state初始值设为空字符串,符合输入框的value类型要求,消除React警告。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 22:14:54