React中RTK Query简易解析:是否替代Axios及表单交互实践
RTK Query 简易解释 + 实战代码示例
一、RTK Query 到底是什么?会替代 Axios 吗?
RTK Query 是 Redux Toolkit 自带的数据获取与缓存管理工具,本质是对底层 HTTP 客户端(比如 Axios、fetch)的上层封装——它不会替代 Axios,反而可以搭配 Axios 使用。
你可以把它理解成一个“懒人工具”:平时用 Axios 发请求,你得自己写请求逻辑、处理加载/成功/失败状态、手动管理缓存、写 Redux 状态同步代码;而 RTK Query 把这些重复工作全帮你做了,你只需要定义好请求的端点,剩下的状态、缓存、更新逻辑它自动搞定。
二、实战:React 表单 + Spring Boot 后端的完整流程
我们就用你说的场景:用户填表单提交数据到 Spring Boot 后端存库,之后能通过 CustID 查询数据。下面是具体代码实现:
1. 先配置 RTK Query 的 API 切片
首先装依赖:
npm install @reduxjs/toolkit react-redux
创建 src/services/customerApi.js,这里定义和后端交互的两个接口:提交客户、查询客户:
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; // 创建 API 切片,底层用 fetch(也可以换成 Axios,后面附示例) export const customerApi = createApi({ reducerPath: 'customerApi', // 唯一标识,存在 Redux Store 里的键名 baseQuery: fetchBaseQuery({ baseUrl: 'http://localhost:8080/api/' }), // 你的 Spring Boot 后端地址 endpoints: (builder) => ({ // 提交客户数据的 POST 请求 addCustomer: builder.mutation({ query: (customerData) => ({ url: 'customers', method: 'POST', body: customerData, }), }), // 根据 CustID 查询客户的 GET 请求 getCustomerById: builder.query({ query: (custId) => `customers/${custId}`, }), }), }); // RTK Query 自动生成的 Hooks,直接在组件里用就行 export const { useAddCustomerMutation, useGetCustomerByIdQuery } = customerApi;
如果想用 Axios 代替默认的 fetch,只需要自定义一个 baseQuery:
import axios from 'axios'; import { createApi } from '@reduxjs/toolkit/query/react'; // 自定义 Axios 版的 baseQuery const axiosBaseQuery = async ({ url, method, body }) => { try { const result = await axios({ url: `http://localhost:8080/api/${url}`, method, data: body, }); return { data: result.data }; } catch (err) { return { error: { status: err.response.status, data: err.response.data } }; } }; // 剩下的和上面一样,只是把 baseQuery 换成自定义的 export const customerApi = createApi({ reducerPath: 'customerApi', baseQuery: axiosBaseQuery, endpoints: (builder) => ({ addCustomer: builder.mutation({ query: (customerData) => ({ url: 'customers', method: 'POST', body: customerData, }), }), getCustomerById: builder.query({ query: (custId) => `customers/${custId}`, }), }), }); export const { useAddCustomerMutation, useGetCustomerByIdQuery } = customerApi;
2. 配置 Redux Store
创建 src/app/store.js,把 RTK Query 的 reducer 加到 Store 里:
import { configureStore } from '@reduxjs/toolkit'; import { customerApi } from '../services/customerApi'; export const store = configureStore({ reducer: { // 把 RTK Query 的 reducer 注册到 Store [customerApi.reducerPath]: customerApi.reducer, }, // 必须加这个中间件,处理缓存、请求失效等逻辑 middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(customerApi.middleware), });
3. 在根组件里提供 Store
修改 src/App.js,用 Provider 把 Store 传给所有子组件:
import { Provider } from 'react-redux'; import { store } from './app/store'; import CustomerForm from './components/CustomerForm'; import CustomerQuery from './components/CustomerQuery'; function App() { return ( <Provider store={store}> <div style={{ maxWidth: 600, margin: '2rem auto', padding: '0 1rem' }}> <h1>客户管理系统</h1> <CustomerForm /> <hr /> <CustomerQuery /> </div> </Provider> ); } export default App;
4. 实现表单提交组件
创建 src/components/CustomerForm.js,处理用户输入和提交:
import { useState } from 'react'; import { useAddCustomerMutation } from '../services/customerApi'; function CustomerForm() { const [formData, setFormData] = useState({ firstName: '', lastName: '', city: '', custID: '', }); // 用 RTK Query 生成的 mutation Hook,返回[触发请求的函数, 请求状态] const [addCustomer, { isLoading, isSuccess, error }] = useAddCustomerMutation(); // 处理表单输入变化 const handleInputChange = (e) => { setFormData({ ...formData, [e.target.name]: e.target.value }); }; // 提交表单 const handleSubmit = async (e) => { e.preventDefault(); try { // unwrap() 可以直接拿到成功数据,或者抛出错误 await addCustomer(formData).unwrap(); // 提交成功后清空表单 setFormData({ firstName: '', lastName: '', city: '', custID: '' }); } catch (err) { console.error('提交失败:', err); } }; return ( <form onSubmit={handleSubmit} style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}> <div> <label style={{ display: 'block', marginBottom: '0.5rem' }}>FirstName:</label> <input type="text" name="firstName" value={formData.firstName} onChange={handleInputChange} required style={{ width: '100%', padding: '0.5rem' }} /> </div> <div> <label style={{ display: 'block', marginBottom: '0.5rem' }}>LastName:</label> <input type="text" name="lastName" value={formData.lastName} onChange={handleInputChange} required style={{ width: '100%', padding: '0.5rem' }} /> </div> <div> <label style={{ display: 'block', marginBottom: '0.5rem' }}>City:</label> <input type="text" name="city" value={formData.city} onChange={handleInputChange} required style={{ width: '100%', padding: '0.5rem' }} /> </div> <div> <label style={{ display: 'block', marginBottom: '0.5rem' }}>CustID:</label> <input type="text" name="custID" value={formData.custID} onChange={handleInputChange} required style={{ width: '100%', padding: '0.5rem' }} /> </div> <button type="submit" disabled={isLoading} style={{ padding: '0.7rem', backgroundColor: '#2196F3', color: 'white', border: 'none', borderRadius: '4px', cursor: 'pointer' }} > {isLoading ? '提交中...' : '提交客户数据'} </button> {isSuccess && <p style={{ color: '#4CAF50', margin: '0.5rem 0' }}>数据提交成功!</p>} {error && <p style={{ color: '#F44336', margin: '0.5rem 0' }}>提交失败: {error.data?.message || error.status}</p>} </form> ); } export default CustomerForm;
5. 实现客户查询组件
创建 src/components/CustomerQuery.js,处理 CustID 查询:
import { useState } from 'react'; import { useGetCustomerByIdQuery } from '../services/customerApi'; function CustomerQuery() { const [custId, setCustId] = useState(''); // 用 RTK Query 生成的 query Hook,自动处理请求和缓存 const { data: customer, isLoading, error } = useGetCustomerByIdQuery(custId, { skip: !custId, // 当 CustID 为空时,不发送请求 }); return ( <div> <h2>查询客户信息</h2> <input type="text" placeholder="请输入 CustID" value={custId} onChange={(e) => setCustId(e.target.value)} style={{ width: '100%', padding: '0.5rem', margin: '1rem 0' }} /> {isLoading && <p style={{ color: '#666' }}>加载中...</p>} {error && <p style={{ color: '#F44336' }}>查询失败: {error.data?.message || error.status}</p>} {customer && ( <div style={{ border: '1px solid #eee', padding: '1rem', borderRadius: '4px' }}> <h3>客户详情</h3> <p><strong>FirstName:</strong> {customer.firstName}</p> <p><strong>LastName:</strong> {customer.lastName}</p> <p><strong>City:</strong> {customer.city}</p> <p><strong>CustID:</strong> {customer.custID}</p> </div> )} </div> ); } export default CustomerQuery;
三、RTK Query 在这个流程里的具体角色
- 请求封装:不用你手写 Axios/fetch 请求,定义一次端点,就能在组件里用 Hook 直接调用
- 状态自动管理:自动提供
isLoading、isSuccess、error这些状态,不用你自己在 Redux 里写 Action 和 Reducer - 缓存优化:同一个 CustID 多次查询时,直接返回缓存数据,不用重复发请求;如果数据更新了,会自动刷新缓存
- 简化组件逻辑:组件只需要关注表单交互和数据展示,不用手动处理请求的生命周期(比如开始请求时设 loading,成功后清状态)
内容的提问来源于stack exchange,提问作者Dips
相关产品推荐
相关产品推荐

