首页 / 文章 / 使用RTK查询发送数据:突变处理实用指南

使用RTK查询发送数据:突变处理实用指南

了解如何在 RTK Query 中使用 builder.mutation() 来发送 POST 请求、处理加载与错误状态,以及构建可用的表单组件。

1875 词

简介

之前我们介绍了如何设置 Redux Toolkit Query(RTK Query)以及使用 builder.query() 执行读取操作。这样我们就可以从 API 获取数据并在 React 应用中展示,而无需手动编写 useEffect()useState() 或自定义的获取数据逻辑。

不过,在处理 API 时,仅读取数据还只是其中一半。大多数应用还需要能够在服务器端添加、修改或删除记录的功能。

以下是几种常见场景:

  • 注册表单提交新的账户信息。
  • 登录页面发送凭证以供验证。
  • 博客平台发布新文章。
  • 在线商店下新订单。
  • 待办事项应用保存新添加的任务。

这些操作都会将信息从客户端发送到服务器,通常是通过HTTP POST请求来实现的。

RTK Query并不将POST调用视为查询操作——而是将其视为变更操作

本文将详细介绍如何使用builder.mutation()发送数据。我们会逐行解析代码及各项配置设置,帮助您不仅了解需要输入什么内容,还能理解每部分的作用。

了解HTTP方法

在深入研究代码之前,先了解一下不同的HTTP动词及其用途会很有帮助。

典型的REST API会提供多种操作:

方法 用途 示例
GET 读取数据 获取所有用户
POST 添加新数据
创建用户 PUT 覆盖现有资源 替换用户记录 PATCH 修改资源的部分内容 更改用户姓名 DELETE 删除数据 删除用户

本指南重点介绍POST,即用于在服务器上创建新资源的方法。

为何POST不使用builder.query()

这是初学者常感困惑的问题。

如果builder.query()能够获取数据,为何同样的函数不能将数据发送到服务器?

原因在于每种工具的设计用途不同。

查询

查询的存在目的是获取信息

典型示例:

  • 获取用户
  • 获取产品
  • 获取订单
  • 获取帖子

由于相同的数据可能会被反复请求,查询会自动缓存其结果。

变更操作

变更操作的目的是修改数据

典型示例包括:

  • 创建用户
  • 更新用户
  • 删除用户
  • 登录
  • 注册

变更操作会向服务器发出信号,表明有内容需要更改。

正是基于这种区别,RTK Query才会将变更操作与普通查询分开处理。

我们要构建的内容

我们将创建一个表单,用于向服务器提交新用户信息。

目标端点为:

https://jsonplaceholder.typicode.com/users

而请求体中发送的负载数据则如下所示:

{
  "name": "John Doe",
  "email": "john@example.com"
}

项目结构

src
│
├── app
│   └── store.js
│
├── services
│   └── api.js
│
├── components
│   └── AddUser.jsx
│
├── App.jsx
│
└── main.jsx

Redux 存储的配置保持不变。我们只需添加一个变异端点以及一个处理表单提交的组件。

第一步 — 创建变异端点

打开 API 服务文件:

src/services/api.js

然后在 endpoints 对象中添加新的端点定义。

import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
export const api = createApi({
  reducerPath: "api",  baseQuery: fetchBaseQuery({
    baseUrl: "https://jsonplaceholder.typicode.com/",
  }),  endpoints: (builder) => ({    addUser: builder.mutation({      query: (newUser) => ({
        url: "users",
        method: "POST",
        body: newUser,
      }),    }),  }),});export const {
  useAddUserMutation,
} = api;

让我们逐行来分析。

理解 builder.mutation()

addUser: builder.mutation({

虽然 builder.query() 用于获取数据,但每当需要在服务器上修改某些内容时,就应该使用 builder.mutation()

常见的应用场景包括:

  • 创建用户
  • 注册账户
  • 登录
  • 更新产品信息
  • 删除帖子

每当您的应用在后端写入或修改数据时,mutation都是合适的工具。

了解 query()

query: (newUser) => ({

该函数会接收您从 React 代码中传入的任何数据。

例如,如果您发出如下操作:

addUser({
  name: "John",
  email: "john@example.com",
});

那么名为

newUser

的参数将包含:

{
  name: "John",
  email: "john@example.com"
}

该对象会被作为请求体发送出去。

了解 URL

url: "users",

假设基础 URL 被配置为:

https://jsonplaceholder.typicode.com/

RTK Query 会自动将它们组合成:

https://jsonplaceholder.typicode.com/users

因此您无需手动输入完整地址。

了解方法

method: "POST",

这行代码明确指示 RTK Query 发送 POST 请求。如果省略此行,请求将默认回退为 GET。

了解请求体

body: newUser,

存储在 newUser 中的任何内容都会作为请求载荷被传递,例如:

{
  "name": "John",
  "email": "john@example.com"
}

服务器会按创建时的原样接收该对象。

步骤 2 — 导出生成的钩子

export const {
  useAddUserMutation,
} = api;

就像查询功能会生成自动创建的钩子一样

useGetUsersQuery()

变异操作也会自动生成各自的钩子:

useAddUserMutation()

你无需手动编写这个钩子——RTK Query会根据端点名称为你生成它。

步骤 3 — 创建 React 组件

创建一个新文件:

src/components/AddUser.jsx

并添加以下代码:

import { useState } from "react";
import { useAddUserMutation } from "../services/api";const AddUser = () => {  const [name, setName] = useState("");
  const [email, setEmail] = useState("");  const [
    addUser,
    {
      isLoading,
      isSuccess,
      error,
    },
  ] = useAddUserMutation();  const handleSubmit = async (e) => {    e.preventDefault();    await addUser({
      name,
      email,
    });    setName("");
    setEmail("");  };  return (
    <form onSubmit={handleSubmit}>      <input
        type="text"
        placeholder="Enter Name"
        value={name}
        onChange={(e) => setName(e.target.value)}
      />      <input
        type="email"
        placeholder="Enter Email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
      />      <button type="submit">
        Add User
      </button>      {isLoading && <p>Saving...</p>}      {isSuccess && <p>User Added Successfully.</p>}      {error && <p>Something went wrong.</p>}    </form>
  );};export default AddUser;

让我们来分析这里发生的具体过程。

理解 useAddUserMutation()

const [
  addUser,
  {
    isLoading,
    isSuccess,
    error,
  },
] = useAddUserMutation();

与查询钩子不同,变异钩子返回的是数组而非对象。第一个元素为:

addUser

这是用于触发请求的函数,而第二个元素是一个包含该请求相关状态信息的对象。

理解 addUser()

await addUser({
  name,
  email,
});

调用此函数会发起如下请求:

POST /users

携带的 JSON 数据格式如下:

{
  "name": "John",
  "email": "john@example.com"
}

在后台,该数据会被用来创建一个全新的用户记录。

理解状态变化

除了触发函数之外,RTK Query 还会提供若干状态标志,用于描述请求的当前处理情况。

isLoading

isLoading

当正在执行数据更新操作时,此标志会变为 true,因此非常适合用于禁用提交按钮或显示加载指示器,直到收到响应为止。

isSuccess

isSuccess

当请求无误完成时,该值将为 true,从而为你提供明确的信号,以便显示确认消息或将用户引导至其他页面。

error

error

如果服务器返回失败响应,相关详细信息会显示在这里,这样你就能呈现可读的错误信息,而不会导致界面异常。

第4步 — 渲染组件

打开主应用程序文件:

src/App.jsx

并将其内容替换为以下内容:

import AddUser from "./components/AddUser";
function App() {
  return <AddUser />;
}export default App;

然后启动开发服务器:

npm run dev

填写表单字段并点击Add User——RTK Query会自动为你发送POST请求。

完整的请求流程

以下是从表单提交到状态更新,整个过程中所发生情况的总结:

User Fills Form
        │
        ▼
Clicks Submit
        │
        ▼
addUser()
        │
        ▼
Generated Mutation Hook
        │
        ▼
RTK Query
        │
        ▼
fetchBaseQuery()
        │
        ▼
POST Request
        │
        ▼
Server Response
        │
        ▼
Mutation State Updates
        │
        ▼
React Re-renders

注意此流程中缺失的所有内容:

  • fetch()
  • axios.post()
  • useEffect()
  • 手动跟踪加载状态
  • 手动跟踪错误状态

RTK Query 在幕后处理了这一切。

builder.query()builder.mutation()

掌握何时使用这些构建器方法非常重要。

builder.query()用于通过GET请求等方式获取数据,它会生成诸如useGetUsersQuery()这样的钩子,在组件渲染时自动执行。相比之下,builder.mutation()则是通过POST、PUT、PATCH或DELETE等方法来修改数据,它生成的钩子如useAddUserMutation(),只有在明确调用触发函数时才会执行,而不会在组件渲染时自动运行。简而言之,查询用于读取数据,而变异操作则用于创建、更新或删除数据。

为每项任务选择合适的工具,能让API逻辑保持一致且易于理解。

最佳实践

使用RTK Query构建POST功能时,请始终牢记以下准则:

  • 每当需要修改服务器上的数据时,就使用builder.mutation()
  • 保持请求体简洁,仅发送后端实际需要的字段。
  • 务必处理isLoadingisSuccesserror状态,以便界面能够及时反馈信息。
  • 选择具有描述性的端点名称,如addUsercreatePostregisterUser
  • 在将用户输入发送到服务器之前对其进行验证。
  • 如果希望在使用组件内的try...catch块来处理成功与失败情况,可考虑使用unwrap()函数。
  • 核心要点

    通过学习本指南,您已经掌握了如何:

    • 使用builder.mutation()创建mutation。
    • 在API slice中配置POST端点。
    • 将JSON数据发送到后端服务。
    • 使用自动生成的 useAddUserMutation() 钩子。
    • 直接从 React 表单发起 POST 请求。
    • 无需手动编写冗余代码即可管理加载、成功和错误状态。
    • 区分查询与修改操作。
    • 采用最佳实践来构建易于维护的 API 交互。

    这种模式在各类生产级应用中随处可见——用户注册流程、身份验证、发布博客文章、下订单以及无数其他数据创建场景。

    接下来学什么?

    掌握了 POST 请求之后,下一步自然是要学习如何更新和删除现有记录。

    即将推出的指南将涵盖:

    • 使用 PUTPATCH 请求更新记录。
    • 通过 DELETE 请求删除记录。
  • 将动态 ID 传递给变更端点。
  • 使缓存数据失效,从而自动刷新用户界面。
  • 使用 providesTagsinvalidatesTags 这两个标签,无需手动重新获取数据即可保持所有内容同步。
  • 读完该指南后,您将能够运用适用于生产环境的 RTK Query 模式来构建完整的 CRUD 应用程序。

    相关阅读