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

Next.js中LocalStorage刷新后值恢复初始值的问题排查

问题分析与解决

你的代码出现刷新后LocalStorage值变回1的核心原因是组件挂载时的初始值写入逻辑覆盖了之前存储的内容,具体执行流程如下:

  1. 组件首次挂载(或刷新页面)时,useState(1)先将testNum初始化为固定值1。
  2. 依赖testNum的useEffect会立即触发,把当前的testNum(也就是1)写入LocalStorage,直接覆盖了之前点击按钮后存储的4。
  3. 此时读取LocalStorage的useEffect才执行,但读到的已经是刚写入的1,最终页面和存储值都回到了初始状态。

简单来说,你通过两个useEffect实现的逻辑导致了「先写初始值,再读旧值」的错误,同时初始state没有优先从LocalStorage读取,而是直接用了固定值。


修复后的代码

import { useState, useEffect } from 'react'

function Test() {
    // 初始化state时优先从LocalStorage读取,无存储值则用默认值1
    const [testNum, setTestNum] = useState(() => {
        const data = window.localStorage.getItem("MY_TEST_ITEM");
        return data ? JSON.parse(data) : 1;
    });

    // 仅保留同步逻辑:testNum变化时更新LocalStorage
    useEffect(() => {
        window.localStorage.setItem("MY_TEST_ITEM", JSON.stringify(testNum))
    }, [testNum]);

    return (
        <div>
            <h1>{testNum}</h1>
            <button onClick={() => setTestNum(prev => prev + 3)}>Add</button>
        </div>
    )
}

export default Test

关键修复点

  1. 用函数式初始化state:在组件挂载时直接读取LocalStorage,避免初始渲染后异步修改state导致的页面闪烁和存储覆盖问题。
  2. 移除多余的读取逻辑:不再需要单独的useEffect来读取存储,初始值已经在state初始化阶段处理完成。
  3. 函数式更新state:点击事件中使用setTestNum(prev => prev + 3),确保在多次快速点击时能正确累加(属于React状态更新的最佳实践)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 01:35:20