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

GraphQL+Rails删除Bicycle后UI未自动更新问题求助

问题解决:Rails GraphQL删除记录后UI不自动更新

在Relay环境下,删除记录后UI不会自动更新是因为Relay无法自动识别需要从哪个列表缓存中移除该记录,需要手动处理缓存更新。以下是具体解决方案:

1. 修正Mutation返回值(前后端对齐)

首先确保前端Mutation的返回字段与类型定义、后端Resolver一致,让Relay能拿到被删除记录的ID:

const [commitDelete, isInFlight] = useMutation<DeleteBicycleMutation>(
  graphql`
      mutation BicycleListDeleteBicycleMutation($input: DeleteBicycleMutationInput!) {
          deleteBicycle(input: $input) {
              deletedBicycleId
          }
      }
  `
);

后端Rails的GraphQL Mutation Resolver也要对应返回deleted_bicycle_id:

class Mutations::DeleteBicycle < Mutations::BaseMutation
  argument :id, ID, required: true

  field :deleted_bicycle_id, ID, null: true

  def resolve(id:)
    bicycle = Bicycle.find(id)
    bicycle.destroy
    { deleted_bicycle_id: id }
  end
end

2. 添加缓存更新逻辑(Updater函数)

在调用commitDelete时,通过updater函数手动从对应列表的Connection缓存中删除节点:

import { ConnectionHandler, RecordSourceSelectorProxy } from 'relay-runtime';

const handleDeleteClick = (bicycle: BicycleRow_bicycle$data, connectionsID: string) => {
    commitDelete({
        variables: {
            input: {
                id: bicycle.id,
            },
        },
        // 手动更新Relay缓存
        updater: (store: RecordSourceSelectorProxy) => {
            const connection = store.get(connectionsID);
            if (connection) {
                ConnectionHandler.deleteNode(connection, bicycle.id);
            }
        },
        // 乐观更新:立即在UI上移除记录,提升体验
        optimisticResponse: {
            deleteBicycle: {
                deletedBicycleId: bicycle.id,
            },
        },
        onCompleted: (response) => {
            console.log("删除成功,ID:", response.deleteBicycle?.deletedBicycleId);
        },
        onError: (error) => {
            console.error("删除失败:", error);
        },
    });
};

3. 确保正确获取Connection ID

在列表组件中,需要拿到对应Connection的ID并传递给删除函数。如果使用usePaginationFragment,可以通过数据的__id属性获取:

const { data } = usePaginationFragment(
  graphql`
      fragment BicycleList_bicycles on Query
      @argumentDefinitions(
          first: { type: "Int", defaultValue: 10 }
          after: { type: "String" }
      ) {
          bicycles(first: $first, after: $after)
          @connection(key: "BicycleList_bicycles") {
              edges {
                  node {
                      id
                      # 其他字段
                  }
              }
          }
      }
  `,
  props.bicycles
);

// 获取Connection的ID
const connectionId = data.bicycles?.__id;

将这个connectionId作为参数传给handleDeleteClick即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 15:03:26