如何为RTKQ中单个待办项的删除按钮实现加载状态
问题描述
我基于Redux Toolkit Query(RTKQ)开发了一个待办事项练习项目,已在apiSlice.js中实现四个核心接口:
- 获取待办项数组
- 创建待办项
- 更新待办项
- 删除待办项
需求是:点击单个待办项的删除按钮时,仅该按钮文本从“delete”变为“loading...”,只为目标待办项的按钮启用加载状态。
尝试过两种方案但未达预期:
- 从
useGetTodosQuery()解构isLoading:仅适用于查询数据的加载状态,无法追踪mutation操作状态; - 从
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
相关产品推荐
相关产品推荐

