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

React按钮激活状态在localStorage中被覆盖,刷新后状态丢失

问题分析与解决方案

问题根源

按钮刷新后状态丢失,核心原因是组件初始化时,写入localStorage的useEffect会先把初始的false值存入,直接覆盖了之前存储的true。具体流程:

  1. Button组件初始化,selected状态默认设为false
  2. 挂载阶段执行两个useEffect:
    • 读取localStorage的useEffect是异步更新状态,不会立即生效
    • 写入localStorage的useEffect先触发,将当前的false存入,覆盖了之前的true值
  3. 等读取localStorage的useEffect完成状态更新,虽会再次写入true,但刷新页面时该顺序重复,最终localStorage仍被重置为false

修复方案

直接在useState初始化时从localStorage读取值,替代原来的第一个useEffect。这样组件初始状态直接使用本地存储的值,避免异步更新导致的覆盖问题。

修改后的Button组件代码:

import React, { useState, useEffect } from "react";

function Button(props) {
  // 初始化时直接从localStorage读取状态,仅在组件首次渲染时执行一次
  const [selected, setSelected] = useState(() => {
    const savedState = window.localStorage.getItem(`selected-${props.title}`);
    return savedState !== null ? JSON.parse(savedState) : false;
  });

  const handleClick = () => {
    setSelected(!selected);
  };

  // 监听selected变化,同步到localStorage,添加props.title作为依赖避免key变化时未同步
  useEffect(() => {
    window.localStorage.setItem(
      `selected-${props.title}`,
      JSON.stringify(selected)
    );
  }, [selected, props.title]);

  return (
    <button
      className={`button-${selected ? "selected" : "not-selected"}`}
      onClick={handleClick}
    >
      <h3>{props.title}</h3>
      <p className="description">{props.description}</p>
    </button>
  );
}

export default Button;

额外说明

  • 使用useState的回调初始化函数:仅在组件首次渲染时执行一次,避免重复读取localStorage
  • 添加props.title到useEffect依赖数组:若按钮title发生变化,能同步更新对应的localStorage键值对

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 00:05:22