如何用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;
几个关键优化点
- 批量更新优化:如果你的后端支持批量更新的GraphQL Mutation(比如接收一个item数组),建议改成批量请求,减少网络开销。比如定义这样的Mutation:
const BATCH_UPDATE_POSITIONS = gql` mutation BatchUpdatePositions($items: [ItemPositionInput!]!) { batchUpdateItemPositions(items: $items) { id position } } `;
然后在排序回调里一次性传递所有需要更新的item,而不是逐个发起请求。
- 缓存自动更新:如果你的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 } }); }} >
- 性能优化:排序时只更新位置变化的item,避免不必要的网络请求,这点在代码里已经处理了。
内容的提问来源于stack exchange,提问作者schingeldi
相关产品推荐
相关产品推荐

