我有一个简单的 redux-toolkit 查询实践项目。
我正在名为
apiSlice.js
的文件中处理四个查询
目的:我试图在单击删除按钮时处理单个目标待办事项的加载状态,如果我单击待办事项的删除按钮,则该按钮的文本将从“删除”更改为“正在加载...”。
可用的解决方案: *没有给我我想要的
首先:我尝试从
isLoading
解构 useGetTodosQuery()
,但它只适用于获取数据,而不是突变
第二:我在这个link中从redux-toolkit文档中找到了一个解决方案,它解释了如何从突变查询的HOOK中解构
isLoading
,例如删除useDeleteTodoMutation()
等......
加载工作高效,但它启用了整个按钮的加载状态
RTKQ 源代码
apiSlice.js
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
const API = 'http://localhost:3500'
export const apiSlice = createApi({
tagTypes: ['Todos'],
reducerPath: 'todos',
baseQuery: fetchBaseQuery({ baseUrl: API }),
endpoints: (builder) =>
({
getTodos: builder.query({
query: () => '/todos',
transformResponse: res => res.sort((a, b) => b.id - a.id),
providesTags: ['Todos']
}),
addTodo: builder.mutation({
query: (todo) => ({
url: '/todos',
method: 'POST',
body: todo
}),
invalidatesTags: ['Todos']
}),
updateTodo: builder.mutation({
query: (todo) => ({
url: `/todos/${todo.id}`,
method: 'PATCH',
body: todo
}),
invalidatesTags: ['Todos']
}),
deleteTodo: builder.mutation({
query: ({ id }) => ({
url: `/todos/${id}`,
method: 'DELETE',
body: id
}),
invalidatesTags: ['Todos']
})
})
})
export const { useGetTodosQuery, useAddTodoMutation, useUpdateTodoMutation, useDeleteTodoMutation } = apiSlice
=> 的源代码
TodoList.js
// add imports
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faTrash, faUpload } from '@fortawesome/free-solid-svg-icons'
import { useState } from "react"
import { useAddTodoMutation, useDeleteTodoMutation, useGetTodosQuery, useUpdateTodoMutation } from '../api/apiSlice'
import { nanoid } from '@reduxjs/toolkit'
const TodoList = () => {
const [newTodo, setNewTodo] = useState('')
const handleSubmit = (e) => {
e.preventDefault();
//addTodo
addTodo({ id: nanoid, title: newTodo, completed: false })
setNewTodo('')
}
const [load, setLoad] = useState(false)
const handleDeleting = (e, todo) => {
deleteTodo(todo)
console.log(e)
if (e.target.id == todo.id) setLoad(true)
}
console.log('loading', load)
const { data: todos, isLoading, isSuccess, isError, error } = useGetTodosQuery()
const [addTodo] = useAddTodoMutation()
const [updateTodo] = useUpdateTodoMutation()
const [deleteTodo, { isLoading: isDeleting }] = useDeleteTodoMutation()
console.log(isDeleting)
const newItemSection =
<form onSubmit={handleSubmit}>
<label htmlFor="new-todo">Enter a new todo item</label>
<div className="new-todo">
<input
type="text"
id="new-todo"
value={newTodo}
onChange={(e) => setNewTodo(e.target.value)}
placeholder="Enter new todo"
/>
</div>
<button className="submit">
<FontAwesomeIcon icon={faUpload} />
</button>
</form>
let content;
// Define conditional content
content = JSON.stringify(todos)
if (isLoading) {
content = <mark>Loading...</mark>
} else if (isSuccess) {
content = todos.map((todo) => (
<article key={todo?.id}>
<input type='checkbox' onChange={() => updateTodo({ ...todo, completed: !todo?.completed })} checked={todo?.completed} id={todo?.id} />
<label htmlFor={todo?.id} >{todo?.title}</label>
<button id={todo.id} style={{ minWidth: '81.16px' }} onClick={(e) => handleDeleting(e, todo)}>{isDeleting ? 'loading...' : 'delete'}</button>
</article>
))
}
return (
<main>
<h1>Todo List</h1>
{newItemSection}
{content}
</main>
)
}
export default TodoList
项目图片
用户界面图像 在此输入图片描述
我的负载 在此输入图片描述
我想要的加载=>我正在删除的绿色,我只想加载状态对其起作用。我没有点击红色,并且我不想在其上启用加载状态 在此输入图片描述
我正在尝试仅为目标待办事项启用加载状态,而不是其他待办事项
注意 我使用
Microsoft's Copilot AI
找到了如下所示的解决方案
import { useDeleteTodoMutation } from '../services/todoService';
function TodoList({ todos }) {
const [deleteTodo, { isLoading }] = useDeleteTodoMutation();
const [deletingTodoId, setDeletingTodoId] = useState(null);
const handleDelete = async (id) => {
setDeletingTodoId(id);
if (window.confirm('Are you sure you want to delete this todo?')) {
try {
await deleteTodo(id).unwrap();
} catch (error) {
console.error('Failed to delete the todo: ', error);
} finally {
setDeletingTodoId(null);
}
}
};
return (
<div>
{todos.map((todo) => (
<div key={todo.id}>
<p>{todo.text}</p>
<button
onClick={() => handleDelete(todo.id)}
disabled={isLoading && deletingTodoId === todo.id}
>
{isLoading && deletingTodoId === todo.id ? 'Deleting...' : 'Delete'}
</button>
</div>
))}
</div>
);
}
提前致谢
您可以使用 event.currentTarget.id 获取目标数据 id 或将目标按钮 id 保存在状态中,因此您可以将其与 .map 数据中的 id 进行比较,如果它等于目标按钮的 id 则启用加载,否则不执行任何操作