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

如何基于RTK Query请求类型优雅控制toast提示展示

针对RTK Query端点自定义Toast规则的实现方案

最简洁优雅的实现方式是利用RTK Query原生支持的extraOptions端点配置字段,不需要在中间件里硬编码接口名单,配置和接口定义绑定,维护成本极低。


实现步骤

1. 在端点定义处配置个性化规则

RTK Query的每个endpoint都支持传入extraOptions字段,该字段会原封不动挂载到对应请求生成的action的meta.arg属性上,你可以在这里直接标记不需要提示的接口,或者给特定接口配置自定义提示文案、关闭时长等规则:

// api服务定义文件示例
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'

export const appApi = createApi({
  baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
  endpoints: (builder) => ({
    // 不需要展示任何toast的后台静默拉取接口
    getBackgroundConfig: builder.query({
      query: () => '/system/config',
      extraOptions: { disableToast: true } // 标记关闭toast
    }),
    // 需要自定义成功/失败提示的操作类接口
    submitForm: builder.mutation({
      query: (formData) => ({
        url: '/form/submit',
        method: 'POST',
        body: formData
      }),
      extraOptions: {
        toastConfig: {
          successMsg: '表单提交成功',
          errorMsg: '提交失败,请检查网络后重试'
        }
      }
    }),
    // 不需要额外配置的接口,自动走全局默认toast规则
    deleteItem: builder.mutation({
      query: (id) => ({url: `/item/${id}`, method: 'DELETE'})
    })
  })
})

2. 改造中间件读取配置

在中间件执行toast逻辑前,先读取当前请求携带的extraOptions配置,优先处理跳过规则,再合并自定义配置覆盖默认逻辑:

import {
  isFulfilled,
  isPending,
  isRejectedWithValue,
  Middleware,
} from "@reduxjs/toolkit";
import { toast } from "react-toastify";

const queryStatus: Middleware = () => (next) => (action) => {
  const TOAST_QUERY_ID = "query-status";
  // 非RTK Query请求直接放行
  if (!isPending(action) && !isFulfilled(action) && !isRejectedWithValue(action)) {
    return next(action);
  }

  // 读取当前端点的自定义配置
  const { disableToast = false, toastConfig = {} } = action.meta.arg.extraOptions || {};
  // 标记关闭toast的请求直接放行,不做提示处理
  if (disableToast) {
    return next(action);
  }

  // 全局默认toast配置
  const defaultConfig = {
    loadingMsg: "请求处理中",
    successMsg: "操作成功",
    errorMsg: "请求出错,请稍后重试",
    successAutoClose: 2000,
    errorAutoClose: 3000,
  };
  // 合并端点自定义配置
  const finalConfig = { ...defaultConfig, ...toastConfig };

  if (isPending(action)) {
    toast(finalConfig.loadingMsg, {
      isLoading: true,
      toastId: TOAST_QUERY_ID,
      type: toast.TYPE.DEFAULT,
    });
  } else if (isFulfilled(action)) {
    const isMutation = action.meta.arg.type === "mutation";
    toast.update(TOAST_QUERY_ID, {
      render: isMutation ? finalConfig.successMsg : "",
      type: toast.TYPE.SUCCESS,
      isLoading: false,
      autoClose: isMutation ? finalConfig.successAutoClose : 100,
    });
  } else if (isRejectedWithValue(action)) {
    toast.update(TOAST_QUERY_ID, {
      render: finalConfig.errorMsg,
      type: toast.TYPE.ERROR,
      isLoading: false,
      autoClose: finalConfig.errorAutoClose,
    });
  }
  return next(action);
};

export default queryStatus;

方案优势

  • 配置和接口定义强绑定,新增/修改接口规则时不需要翻找中间件代码,不会出现硬编码名单漏改、错改的问题
  • 基于官方原生扩展能力实现,没有hack逻辑,版本兼容性好
  • 扩展性强,后续如果需要给特定接口加toast持久显示、自定义交互、操作跳转等逻辑,只需要在extraOptions里新增对应字段,在中间件里统一处理即可
  • 完全兼容你之前实现的query/mutation差异化逻辑,不需要重构原有代码

内容的提问来源于stack exchange,提问作者Osmanys Fuentes-Lombá

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 05:18:19