GraphQL查询返回只读对象报错,如何预处理数据移除非字母数字字符?
GraphQL查询返回只读对象的预处理方案
Apollo Client(你使用的useQuery大概率基于Apollo)返回的查询结果是被冻结的只读对象,直接修改字段会触发Cannot assign to read only property错误,以下是两种可行的预处理方案:
方案一:通过状态存储处理后的副本
用useState保存处理后的数据,在onCompleted回调中先拷贝原数据,再修改字段:
import { useState } from 'react'; import { useQuery } from '@apollo/client'; // 你的类型定义 export interface MyObject { id: string; fName?: string; lName?: string; dateOfBirth?: string; } // 组件内代码 const [processedData, setProcessedData] = useState<MyObject | null>(null); const { loading: isDataLoading, data: myData } = useQuery(getData, { variables: { id }, onCompleted: (data) => { // 深拷贝原数据,避开只读限制 const clonedData = JSON.parse(JSON.stringify(data.data)); // 清理dateOfBirth字段(注意:当前正则是移除字母数字,若需保留字母数字请改用/[^a-zA-Z0-9]/g) if (clonedData.dateOfBirth) { clonedData.dateOfBirth = clonedData.dateOfBirth.replace(/[a-zA-Z0-9]/g, ''); } // 按需处理其他字段 if (clonedData.fName) { clonedData.fName = clonedData.fName.replace(/[a-zA-Z0-9]/g, ''); } if (clonedData.lName) { clonedData.lName = clonedData.lName.replace(/[a-zA-Z0-9]/g, ''); } setProcessedData(clonedData); } });
方案二:使用transformResponse钩子(推荐)
Apollo提供了transformResponse选项,能在数据进入缓存前完成转换,后续直接使用处理后的结果,无需额外状态:
import { useQuery } from '@apollo/client'; export interface MyObject { id: string; fName?: string; lName?: string; dateOfBirth?: string; } // 组件内代码 const { loading: isDataLoading, data: myData } = useQuery(getData, { variables: { id }, transformResponse: (response) => { const rawItem = response.data; // 生成处理后的对象 const processedItem: MyObject = { ...rawItem, dateOfBirth: rawItem.dateOfBirth?.replace(/[a-zA-Z0-9]/g, '') ?? '', fName: rawItem.fName?.replace(/[a-zA-Z0-9]/g, '') ?? '', lName: rawItem.lName?.replace(/[a-zA-Z0-9]/g, '') ?? '' }; // 保持返回结构与原响应一致 return { data: processedItem }; } });
注意事项
- 深拷贝方式:
JSON.parse(JSON.stringify())适合简单数据结构,若你的对象包含日期、函数等特殊类型,建议使用lodash的cloneDeep或自定义递归拷贝函数。 - 正则修正:如果你的需求是保留字母数字、移除其他字符,请将正则改为
/[^a-zA-Z0-9]/g(当前正则逻辑是移除字母数字)。
内容的提问来源于stack exchange,提问作者boing
相关产品推荐
相关产品推荐

