You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 };
  }
});

注意事项

  1. 深拷贝方式:JSON.parse(JSON.stringify())适合简单数据结构,若你的对象包含日期、函数等特殊类型,建议使用lodash的cloneDeep或自定义递归拷贝函数。
  2. 正则修正:如果你的需求是保留字母数字、移除其他字符,请将正则改为/[^a-zA-Z0-9]/g(当前正则逻辑是移除字母数字)。

内容的提问来源于stack exchange,提问作者boing

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 23:10:43