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

如何用Apollo Client 2.1的Mutation组件实现批量更新(Batch Mutations)

实现排序后批量更新位置的完整方案

结合你已经有的基础查询,我来梳理一下用Apollo Client 2.1 + react-sortable-hoc实现需求的完整流程:

1. 先导入所需依赖

首先把要用的工具库都引入进来:

import React from 'react';
import { Query, Mutation } from 'react-apollo';
import gql from 'graphql-tag';
import { SortableContainer, SortableElement, arrayMove } from 'react-sortable-hoc';

2. 定义GraphQL查询和Mutation

保留你的基础查询,同时新增一个用于更新单条item位置的Mutation(如果后端支持批量更新,后面会说优化方案):

// 你的基础查询
const GET_ITEMS = gql`
  {
    items(order: { by: "position", direction: "desc" }) {
      id
      name
      position
    }
  }
`;

// 更新单个item位置的Mutation
const UPDATE_ITEM_POSITION = gql`
  mutation UpdateItemPosition($id: ID!, $position: Int!) {
    updateItem(id: $id, position: $position) {
      id
      position
    }
  }
`;

3. 创建可排序的组件

用react-sortable-hoc包装列表项和容器,实现拖拽排序的UI:

// 单个可排序的列表项
const SortableItem = SortableElement(({ item }) => (
  <div style={{ padding: '8px', border: '1px solid #eee', marginBottom: '4px' }}>
    {item.name} — 当前位置: {item.position}
  </div>
));

// 可排序的列表容器
const SortableList = SortableContainer(({ items, onSortEnd }) => (
  <div>
    {items.map((item, index) => (
      <SortableItem 
        key={`sortable-item-${item.id}`} 
        index={index} 
        item={item} 
      />
    ))}
  </div>
));

4. 主组件逻辑:查询、排序、更新

在主组件里整合查询数据、处理排序回调、批量更新位置的逻辑:

const SortableItemList = () => {
  // 处理排序结束后的批量更新逻辑
  const handleSortCompletion = ({ oldIndex, newIndex }, originalItems, updatePosition) => {
    // 生成排序后的新列表(用扩展运算符避免修改原数组)
    const sortedItems = arrayMove([...originalItems], oldIndex, newIndex);
    
    // 遍历新列表,只更新位置变化的item
    // 这里假设后端position从1开始计数,根据你的实际规则调整(比如从0开始就直接用index)
    const updateTasks = sortedItems.map((item, index) => {
      const newPosition = index + 1;
      if (item.position !== newPosition) {
        return updatePosition({ 
          variables: { id: item.id, position: newPosition } 
        });
      }
      return Promise.resolve();
    });

    // 等待所有更新完成,可在这里添加成功/失败提示
    Promise.all(updateTasks)
      .then(() => alert('所有位置已更新完成'))
      .catch(err => console.error('位置更新失败:', err));
  };

  return (
    <Query query={GET_ITEMS}>
      {({ loading, error, data }) => {
        if (loading) return <div>加载中...</div>;
        if (error) return <div>加载出错: {error.message}</div>;

        const { items } = data;

        return (
          <Mutation mutation={UPDATE_ITEM_POSITION}>
            {(updatePosition) => (
              <SortableList
                items={items}
                onSortEnd={(event) => handleSortCompletion(event, items, updatePosition)}
                lockAxis="y" {/* 限制垂直排序,可选配置 */}
              />
            )}
          </Mutation>
        );
      }}
    </Query>
  );
};

export default SortableItemList;

几个关键优化点

  1. 批量更新优化:如果你的后端支持批量更新的GraphQL Mutation(比如接收一个item数组),建议改成批量请求,减少网络开销。比如定义这样的Mutation:
const BATCH_UPDATE_POSITIONS = gql`
  mutation BatchUpdatePositions($items: [ItemPositionInput!]!) {
    batchUpdateItemPositions(items: $items) {
      id
      position
    }
  }
`;

然后在排序回调里一次性传递所有需要更新的item,而不是逐个发起请求。

  1. 缓存自动更新:如果你的Mutation返回了id和position字段,Apollo Client会自动更新缓存中的对应数据,查询列表会自动刷新。如果没有自动更新,可以在Mutation组件里手动处理缓存:
<Mutation 
  mutation={UPDATE_ITEM_POSITION}
  update={(cache, { data: { updateItem } }) => {
    // 读取缓存中的items
    const { items } = cache.readQuery({ query: GET_ITEMS });
    // 更新对应item的位置
    const updatedItems = items.map(item => 
      item.id === updateItem.id ? { ...item, position: updateItem.position } : item
    );
    // 写回缓存
    cache.writeQuery({ query: GET_ITEMS, data: { items: updatedItems } });
  }}
>
  1. 性能优化:排序时只更新位置变化的item,避免不必要的网络请求,这点在代码里已经处理了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 11:10:47