Zustand从IndexedDB恢复状态后重渲染异常问题求助
Zustand 从IndexedDB恢复状态后重渲染失效问题
问题现象
首次加载时功能正常,但页面刷新从IndexedDB恢复状态后,执行updateNodeText更新文本后,其他组件无法重渲染展示更新后的内容。排查一周未找到原因,怀疑和Immer的produce方法有关。
问题核心代码
if (state.selectedNode.node.type === "JSXText") { state.selectedNode.node.value = text; }
问题根源
- 状态引用断裂:从IndexedDB恢复的
selectedNode是独立的序列化对象,和projects数组中存储的真实节点没有引用关联。修改selectedNode.node.value只是修改了这个独立对象的属性,并没有改动projects里的实际数据,导致依赖projects的组件无法感知到状态变化。 - Immer使用逻辑错误:虽然用了produce包裹,但修改的是未纳入Zustand状态追踪的独立引用,Zustand无法检测到状态变更,自然不会触发重渲染。
修复方案
方案1:直接更新projects中的真实节点(推荐)
修改updateNodeText方法,通过selectedNode的定位信息找到projects里的对应节点并修改,确保状态变更被Zustand正确追踪:
updateNodeText: (text: string) => set( produce((state) => { if (!state.selectedNode) return; const currentProject = state.projects.find(p => p.id === state.currentProjectId); if (!currentProject) return; // 定位到对应页面 const currentPage = currentProject.pages.find(page => page.id === state.selectedNode.pageId); if (!currentPage) return; // 定位到对应组件 const currentComponent = currentPage.components.find(comp => comp.id === state.selectedNode.componentId); if (!currentComponent) return; // 根据你的节点结构实现真实节点查找逻辑,示例假设通过路径定位 const targetNode = findTargetNode(currentComponent, state.selectedNode.node); if (targetNode?.type === "JSXText") { targetNode.value = text; } // 同步更新selectedNode的显示值(可选,保持选中状态一致性) state.selectedNode.node.value = text; }) ),
注:
findTargetNode需要根据你的节点层级结构实现,比如通过节点的唯一标识或路径从组件的children中找到对应节点。
方案2:修正selectedNode的引用关系
在setSelectedNode时,直接引用projects中的真实节点,而不是存储独立的复制对象:
setSelectedNode: (nodeData: {pageId: string, componentId: string, nodeIdentifier: any}) => set( produce((state) => { const currentProject = state.projects.find(p => p.id === state.currentProjectId); if (!currentProject) return; const currentPage = currentProject.pages.find(page => page.id === nodeData.pageId); if (!currentPage) return; const currentComponent = currentPage.components.find(comp => comp.id === nodeData.componentId); if (!currentComponent) return; // 找到projects中的真实节点并引用 const realNode = findTargetNode(currentComponent, nodeData.nodeIdentifier); if (realNode) { state.selectedNode = { pageId: nodeData.pageId, componentId: nodeData.componentId, node: realNode, // 其他必要属性 }; state.selectedPageId = nodeData.pageId; state.selectedComponentId = nodeData.componentId; } }) ),
额外检查点
确认persist的partialize配置是否符合需求:当前配置只持久化projects、selectedComponentId、currentProjectId,selectedNode不会被保存,刷新后会回到初始值null。如果需要保留选中状态,需将selectedNode相关的必要定位信息(而非完整节点对象)加入partialize。
内容的提问来源于stack exchange,提问作者Anni
相关产品推荐
相关产品推荐

