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

React Query:如何优雅编写多useMutation自定义Hook?

Optimizing Your useListMutation Hook to Eliminate Duplication

Great call noticing the repetition in your custom hook—let’s clean this up to make it more maintainable and readable! The core idea is to extract shared logic into reusable helpers, so each mutation only defines the unique part (how it updates the cache).

Here’s the optimized version of your hook:

import * as List from "./list-api";
import { useMutation, queryCache } from 'react-query'; // Assuming these base imports
import { v4 as uuidv4 } from 'uuid';

const useListMutation = (onSettled, onError) => {
  // Extract shared error handling logic
  const handleMutationError = (err, variables, rollback) => {
    rollback();
    onError(err);
  };

  // Extract shared post-settled logic
  const handleMutationSettled = () => {
    queryCache.invalidateQueries("lists");
    onSettled();
  };

  // Factory function to build mutation configs
  const buildMutationConfig = (updateCache) => ({
    onMutate: (variables) => {
      // Shared onMutate setup: cancel pending queries and save current cache state
      queryCache.cancelQueries("lists");
      const currentLists = queryCache.getQueryData("lists");

      // Apply the operation-specific cache update
      queryCache.setQueryData("lists", prev => updateCache(prev, variables));

      // Return rollback function (shared across all mutations)
      return () => queryCache.setQueryData("lists", currentLists);
    },
    onError: handleMutationError,
    onSettled: handleMutationSettled,
  });

  // Create each mutation with its unique cache update logic
  const [createList] = useMutation(List.createList, buildMutationConfig((prev, listTitle) => [
    ...prev,
    { title: listTitle, id: uuidv4() }
  ]));

  const [updateList] = useMutation(List.updateList, buildMutationConfig((prev, { id, titleValue }) => [
    ...prev.filter(list => list._id !== id),
    { _id: id, title: titleValue }
  ]));

  const [deleteList] = useMutation(List.deleteList, buildMutationConfig((prev, id) => 
    prev.filter(list => list._id !== id)
  ));

  return { createList, updateList, deleteList };
};

export default useListMutation;

Key Improvements:

  • Shared Handler Extraction: handleMutationError and handleMutationSettled encapsulate the identical logic across all three mutations. Now if you need to adjust error handling or post-settled behavior, you only change it once.
  • Mutation Config Factory: The buildMutationConfig function takes care of repetitive onMutate setup (canceling queries, saving current cache state, returning the rollback function). You only pass in the unique logic for how that mutation should update the cache.
  • Focused Unique Logic: Each mutation now only defines the part specific to it—how it modifies the list cache. This makes the code easier to scan and debug, since you don’t have to wade through repeated boilerplate to find differences between create/update/delete.

Bonus: Even More Cleanup (Optional)

If you want to separate cache update logic entirely for reusability or clarity, you could define them as standalone functions outside the hook:

// Cache update utilities (can live in a separate file if needed)
const updateCacheForCreate = (prev, listTitle) => [
  ...prev,
  { title: listTitle, id: uuidv4() }
];

const updateCacheForUpdate = (prev, { id, titleValue }) => [
  ...prev.filter(list => list._id !== id),
  { _id: id, title: titleValue }
];

const updateCacheForDelete = (prev, id) => prev.filter(list => list._id !== id);

// Then use them in the hook:
const [createList] = useMutation(List.createList, buildMutationConfig(updateCacheForCreate));
const [updateList] = useMutation(List.updateList, buildMutationConfig(updateCacheForUpdate));
const [deleteList] = useMutation(List.deleteList, buildMutationConfig(updateCacheForDelete));

This is perfect if you want to reuse these cache update functions elsewhere, or keep your hook even more focused on mutation orchestration.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 11:52:27