基于JSON动态创建ReactFlow节点,刷新后按钮失效求助
问题分析与解决方案
核心问题
你的代码存在两个关键问题,导致刷新后按钮失效:
- 异步操作时序错误:
fetch是异步请求,调用handleClick后立刻执行setNodes时,newNodes还没被接口返回的数据更新(React的setState也是异步的),此时用的还是旧的newNodes值。 - 闭包与依赖缺失:
useCallback的依赖数组只传了setNodes,没包含newNodes和handleClick,导致onAdd函数被缓存,一直引用初始渲染时的newNodes空数组,刷新后完全拿不到新数据。
修正方案(推荐简洁版)
直接去掉冗余的newNodes状态,在异步请求回调里直接更新节点列表,避免中间状态带来的闭包问题:
function Flow() { const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes); const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges); const onAdd = useCallback(() => { fetch('/get_nodes') .then((r) => r.json()) .then(data => { console.log(data); // 直接在请求完成后更新节点 setNodes((nds) => nds.concat(data)); }); }, [setNodes]); }
保留newNodes状态的修正方案
如果业务需要保留newNodes中间状态,需正确处理依赖和异步更新:
function Flow() { const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes); const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges); const [newNodes, setNewNodes] = useState([]); // 用useCallback包裹请求函数,添加必要依赖 const handleFetch = useCallback(() => { fetch('/get_nodes') .then((r) => r.json()) .then(data => { console.log(data); setNewNodes(data); }); }, [setNewNodes]); const onAdd = useCallback(() => { handleFetch(); }, [handleFetch]); // 监听newNodes变化,自动更新节点列表 useEffect(() => { if (newNodes.length > 0) { setNodes((nds) => nds.concat(newNodes)); // 可选:清空newNodes防止重复添加 setNewNodes([]); } }, [newNodes, setNodes]); }
补充说明
热重载时按钮能临时工作,是因为React的热更新机制没有完全重置闭包,但刷新浏览器后组件重新初始化,闭包引用的旧值问题就会完全暴露。本质是React状态更新的异步性和闭包特性导致的,和ReactFlow本身无关。
内容的提问来源于stack exchange,提问作者HFX
相关产品推荐
相关产品推荐

