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

React组件卸载时异步保存本地存储失效及自动配置页实现问题

修复配置页面自动加载/保存的问题

核心问题分析

  1. 严格模式异步执行干扰:React开发环境的严格模式会重复执行useEffect的setup和cleaner函数,你的异步loadSettings还未完成就被cleaner打断,导致提前保存了初始空对象。
  2. 闭包捕获旧state:空依赖的useEffect中,cleaner函数捕获的是组件首次渲染时的settings(空对象),后续state更新不会改变这个闭包内的值,因此卸载时始终保存初始状态。

解决方案

1. 用useRef保存最新状态引用

通过useRef同步最新的settings值,让cleaner函数能访问到实时的配置数据。

2. 标记组件挂载状态,过滤无效操作

在开发环境严格模式下,避免未完成的异步操作干扰,同时防止组件卸载后执行setState。

修改后的完整代码

import { useState, useEffect, useRef } from 'react';

const ConfigPage = () => {
  const [settings, setSettings] = useState<settingStruct>({});
  const latestSettingsRef = useRef<settingStruct>({});
  const isMountedRef = useRef(false);

  // 同步最新settings到ref,保证随时能拿到最新值
  useEffect(() => {
    latestSettingsRef.current = settings;
  }, [settings]);

  const loadSettings = async () => {
    if (!isMountedRef.current) return;
    try {
      const savedSetting = await loadJsonFile<settingStruct>("settings.json", {});
      console.log("load: ", savedSetting);
      setSettings(savedSetting!);
    } catch (err) {
      console.error("加载配置失败:", err);
    }
  };

  const saveSettings = async () => {
    const currentSettings = latestSettingsRef.current;
    console.log("save: ", currentSettings);
    try {
      await saveJsonFile('settings.json', currentSettings);
    } catch (err) {
      console.error("保存配置失败:", err);
    }
  };

  useEffect(() => {
    isMountedRef.current = true;
    let isStrictModeReRun = true;
    loadSettings();

    return () => {
      isMountedRef.current = false;
      // 严格模式下首次cleaner是重复执行,跳过保存
      if (!isStrictModeReRun) {
        saveSettings();
      }
      isStrictModeReRun = false;
    };
  }, []);

  useEffect(() => {
    console.log("changed: ", settings);
  }, [settings]);

  // 你的UI组件示例
  return (
    <div>
      <input
        value={settings.authKey || ''}
        onChange={(e) => setSettings({...settings, authKey: e.target.value})}
      />
      <button onClick={saveSettings}>手动保存</button>
    </div>
  );
};

export default ConfigPage;

关键修改说明

  • latestSettingsRef:每次settings更新时同步到ref,彻底解决闭包捕获旧值的问题,确保卸载时保存的是最新配置。
  • isMountedRef:标记组件挂载状态,避免组件卸载后执行setState引发警告。
  • isStrictModeReRun:过滤严格模式下的首次无效cleaner执行,解决开发环境中初始值被错误保存的问题,生产环境不受影响。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 12:25:11