使用RTK Query加载React Force Graph 2D时遇对象不可扩展错误
问题解决:RTK Query数据传入React Force Graph 2D报"对象不可扩展"错误
问题描述
用RTK Query从后端获取数据后传入React Force Graph 2D组件时,出现错误:Uncaught TypeError: Cannot add property __indexColor, object is not extensible,但直接复制网络面板里的响应数据手动传入组件却能正常运行。
原因
RTK Query为避免意外修改缓存数据,默认会对返回的响应数据执行**对象冻结(Object.freeze)**操作,冻结后的对象无法添加新属性。而React Force Graph 2D内部需要给节点对象添加__indexColor这类私有属性,因此触发了不可扩展的错误。
解决方案
方案1:在RTK Query的API定义中深拷贝响应数据
在API的transformResponse钩子中对返回数据进行深拷贝,生成可扩展的新对象:
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; export const graphApi = createApi({ reducerPath: 'graphApi', baseQuery: fetchBaseQuery({ baseUrl: '/api/' }), endpoints: (builder) => ({ getGraphData: builder.query({ query: () => 'graph-data', transformResponse: (response) => { // 用JSON序列化反序列化实现深拷贝(适合普通结构数据) return JSON.parse(JSON.stringify(response)); // 若需支持特殊对象,可改用structuredClone(需浏览器支持ES2022+) // return structuredClone(response); }, }), }), }); export const { useGetGraphDataQuery } = graphApi;
方案2:在组件内深拷贝后再传入组件
如果不想修改API定义,可在组件中拿到数据后先深拷贝,再传给ForceGraph2D:
const { data: rawGraphData } = useGetGraphDataQuery(); // 深拷贝生成可扩展对象 const graphData = rawGraphData ? JSON.parse(JSON.stringify(rawGraphData)) : null; return ( {graphData && ( <ForceGraph2D width={window.innerWidth} height={650} nodeRelSize={10} cooldownTicks={50} nodeCanvasObjectMode={() => 'after'} graphData={graphData} ref={forceRef} nodeCanvasObject={(node, ctx, globalScale) => { const label = node.name; const fontSize = globalScale * 1.2; ctx.font = `${fontSize}px Sans-Serif`; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; ctx.fillStyle = node.isClusterNode ? 'white' : 'black'; const lineHeight = fontSize * 1.2; const x = node.x ?? 0; const y = (node.y ?? 0) - lineHeight; ctx.fillText(label, x, y); }} onNodeClick={handleNodeClick} /> )} );
注意事项
不推荐关闭RTK Query的全局数据冻结机制(会降低Redux状态的安全性),优先使用前两种深拷贝方案。
内容的提问来源于stack exchange,提问作者Aneesh
相关产品推荐
相关产品推荐

