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

如何为RTKQ中单个待办项的删除按钮实现加载状态

问题描述

我基于Redux Toolkit Query(RTKQ)开发了一个待办事项练习项目,已在apiSlice.js中实现四个核心接口:

  • 获取待办项数组
  • 创建待办项
  • 更新待办项
  • 删除待办项

需求是:点击单个待办项的删除按钮时,仅该按钮文本从“delete”变为“loading...”,只为目标待办项的按钮启用加载状态。

尝试过两种方案但未达预期:

  1. 从useGetTodosQuery()解构isLoading:仅适用于查询数据的加载状态,无法追踪mutation操作状态;
  2. 从useDeleteTodoMutation()解构isLoading:该状态是全局的,会导致所有删除按钮同时进入加载状态。
解决方案

要实现单个按钮的独立加载状态,核心是追踪当前正在执行删除操作的待办项ID,而非依赖mutation返回的全局isLoading状态。以下是两种可行实现方式:

方法一:组件状态+mutation回调(推荐,适合简单场景)

在TodoList.js中维护一个状态记录当前正在删除的待办项ID,通过mutation的执行回调更新状态,实现按钮的独立加载控制。

修改后的TodoList.js代码

import { useState } from 'react';
import { useGetTodosQuery, useDeleteTodoMutation } from './apiSlice';

export const TodoList = () => {
  const { data: todos = [] } = useGetTodosQuery();
  const [deleteTodo] = useDeleteTodoMutation();
  // 记录当前正在删除的待办项ID
  const [deletingTodoId, setDeletingTodoId] = useState(null);

  const handleDelete = async (todoId) => {
    setDeletingTodoId(todoId);
    try {
      await deleteTodo(todoId).unwrap();
    } catch (err) {
      // 按需处理删除失败逻辑,比如提示错误
    } finally {
      // 无论成功失败,重置加载状态
      setDeletingTodoId(null);
    }
  };

  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>
          {todo.text}
          <button
            onClick={() => handleDelete(todo.id)}
            disabled={deletingTodoId === todo.id}
          >
            {deletingTodoId === todo.id ? 'loading...' : 'delete'}
          </button>
        </li>
      ))}
    </ul>
  );
};

说明

  • 通过deletingTodoId状态精准标记当前处于加载中的待办项;
  • 点击按钮时先切换状态触发文本变化,执行删除操作后无论结果如何,都重置状态恢复按钮样式。

方法二:RTKQ mutation状态追踪(进阶,适合复杂场景)

利用RTKQ提供的useMutationState钩子,直接查询特定mutation的执行状态,判断当前待办项是否处于删除中。

修改后的TodoList.js代码

import { useGetTodosQuery, useDeleteTodoMutation, useMutationState } from './apiSlice';

export const TodoList = () => {
  const { data: todos = [] } = useGetTodosQuery();
  const [deleteTodo] = useDeleteTodoMutation();
  // 获取所有deleteTodo类型的mutation状态
  const deleteMutations = useMutationState({
    predicate: (mutation) => mutation.endpointName === 'deleteTodo'
  });

  // 判断指定ID的待办项是否正在删除
  const isDeleting = (todoId) => {
    return deleteMutations.some(mutation => 
      mutation.status === 'pending' && mutation.arg === todoId
    );
  };

  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>
          {todo.text}
          <button
            onClick={() => deleteTodo(todo.id)}
            disabled={isDeleting(todo.id)}
          >
            {isDeleting(todo.id) ? 'loading...' : 'delete'}
          </button>
        </li>
      ))}
    </ul>
  );
};

说明

  • useMutationState可以筛选并获取指定类型的mutation状态集合;
  • 通过检查集合中是否存在对应待办项ID的pending状态mutation,来控制按钮的加载显示。

两种方法均可实现需求:点击单个删除按钮时,仅该按钮进入加载状态,其余按钮不受影响,直到当前删除操作完成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 00:33:21