我正在尝试创建一个自动保存配置页面。我希望它可以将配置文件(现在只是一个 json 文件)加载到状态中,然后您可以通过 ui 组件对其进行编辑。当您切换到另一个页面时,状态可以保存回配置文件。我不确定如何实现它。
目前我使用useEffect
第二[]
个参数来执行此操作。根据官方文档,它将在组件挂载时运行作为第一个参数传递的设置函数,并在卸载时运行返回的清理函数。但是,由于加载/保存操作是异步函数,因此它的运行方式与我的预期大不相同。
这是我的代码,包括一些调试日志:
const [settings, setSettings] = useState<settingStruct>({});
const loadSettings = async () => {
const savedSetting = await loadJsonFile<settingStruct>("settings.json", {});
console.log("load: ", settings);
setSettings(savedSetting!);
};
const saveSettings = async () => {
console.log("save: ", settings);
await saveJsonFile('settings.json', settings);
};
useEffect(() => { // here I hope it could achieve auto-load/save
loadSettings();
return () => {
saveSettings();
}
}, []);
useEffect(()=>{
console.log("changed: ", settings)
}, [settings]);
另外我临时添加了一个可以手动触发运行的按钮saveSettings()
。
然后,经过测试,我得到了如下控制台日志:
// switch to the page
changed: {} // init value
save: {} // react's strict mode, run an additional setup and cleaner, however the order is wrong
changed: {} // not sure why it's triggered
load: {} // two setup and changes caused by them
changed: {}
load: {}
changed: {}
changed: {authKey: '1234567'} // here I pasted something to input component, and it triggered state update operation
save: {authKey: '1234567'} // manual save, it looks good
save: {} // cleaner triggered because I switched to another page, but it saved an empty object(specifically the init value), not the latest state
有两个问题,第一个是严格模式调用顺序错误setup -> cleaner -> setup
,我认为是因为它们是异步函数,所以 React 不知道前一个没有完成。这导致 init 值在被加载值更新之前被保存,我不知道如何修复它。不过,这在生产环境中似乎不是问题。
第二个问题,我完全无法理解,就是组件卸载时触发的清理器总是只保存初始值,无论实际状态如何。这导致我的功能完全不可用
我想知道如何修复这些问题,或者如何正确实现此自动保存功能。
请尝试介绍
settingsRef
当发生变化时哪些会更新settings
。settingsRef.current
用于saveSettings
。这样做的解释是,
useEffect
空依赖数组仅被调用一次,因此saveSettings
仅使用初始状态进行渲染。