React中如何在多组件中使用RTK Query的mutation响应数据
RTK Query Mutation响应跨组件无法访问的解决方案
问题背景
使用React 18 + @reduxjs/toolkit 1.9.1开发,表单提交时通过RTK Query的artistSearch mutation触发POST接口,当前组件能正常拿到响应数据并完成页面跳转,但跳转后的目标组件及其他组件无法获取该mutation的响应数据。调用useArtistSearchMutation后打印返回的data结果为undefined。
相关代码
表单提交逻辑:
const formSubmit = async (data) => { const payload = { ... }; try { const response = await artistSearch(payload); if (response) { navigate("/artist-search-results", { state: { data } }); } } catch (artistError) { ... } };
API定义:
export const artistApi = createApi({ reducerPath: "artistApi", baseQuery: fetchBaseQuery({ baseUrl: `...`, headers: { ... }, }), endpoints: (builder) => ({ getArtist: builder.query({ query: (uid) => `/getProfile/${uid}`, }), artistSearch: builder.mutation({ query: (formData) => ({ url: "ArtistListSearch", method: "POST", body: formData, }), }), }), }); export const { useGetArtistQuery, useArtistSearchMutation } = artistApi;
目标组件尝试获取数据的代码:
const [ artistSearch, { data: artistSearchResponse, error: artistError, isLoading: isArtistLoading } ] = useArtistSearchMutation(); console.log("artist search data is:", artistSearchResponse);
原因分析
RTK Query的mutation默认不会全局缓存响应结果,它的状态是组件级别的——只有发起mutation的组件实例能拿到本次调用的响应,其他组件重新调用useArtistSearchMutation时,只会拿到新的初始状态(data为undefined),无法获取之前的调用结果。
解决方法
方法1:路由跳转时传递响应数据
最直接的方式是在跳转时把mutation的响应数据通过路由state传递给目标组件,适合一次性使用的场景:
const formSubmit = async (data) => { const payload = { ... }; try { const response = await artistSearch(payload); if (response) { // 传递mutation返回的响应数据,而非原表单数据 navigate("/artist-search-results", { state: { artistData: response.data } }); } } catch (artistError) { ... } };
目标组件中通过useLocation获取数据:
import { useLocation } from 'react-router-dom'; const ArtistSearchResults = () => { const location = useLocation(); const artistData = location.state?.artistData; console.log('artist search data is:', artistData); // 后续逻辑处理 };
方法2:手动将mutation结果缓存到RTK Query的全局缓存
如果需要在多个组件中长期访问,可以通过onQueryStarted钩子把mutation的响应存入RTK Query的query缓存中:
artistSearch: builder.mutation({ query: (formData) => ({ url: "ArtistListSearch", method: "POST", body: formData, }), // 查询完成后,将响应缓存到getArtist接口的指定key下 onQueryStarted: async (arg, { queryFulfilled, dispatch }) => { const { data } = await queryFulfilled; // 这里的'search_result'是自定义的缓存key,可根据需求修改 dispatch( artistApi.util.updateQueryData('getArtist', 'search_result', () => data) ); }, }),
然后在其他组件中通过useGetArtistQuery获取缓存数据:
// skip设为false确保直接读取缓存 const { data: artistSearchResponse } = useGetArtistQuery('search_result', { skip: false }); console.log('artist search data is:', artistSearchResponse);
方法3:存入Redux全局状态
如果需要更灵活的全局状态管理,可以创建自定义Redux slice来存储mutation响应:
- 创建slice:
import { createSlice } from '@reduxjs/toolkit'; const artistSearchSlice = createSlice({ name: 'artistSearch', initialState: { result: null, }, reducers: { setArtistSearchResult: (state, action) => { state.result = action.payload; }, clearArtistSearchResult: (state) => { state.result = null; }, }, }); export const { setArtistSearchResult, clearArtistSearchResult } = artistSearchSlice.actions; export default artistSearchSlice.reducer;
在store中注册该slice(确保store已配置RTK Query的middleware)。
提交表单时dispatch保存数据的action:
import { useDispatch } from 'react-redux'; import { setArtistSearchResult } from './path/to/artistSearchSlice'; const formSubmit = async (data) => { const dispatch = useDispatch(); const payload = { ... }; try { const response = await artistSearch(payload); if (response) { dispatch(setArtistSearchResult(response.data)); navigate("/artist-search-results"); } } catch (artistError) { ... } };
- 其他组件通过
useSelector获取数据:
import { useSelector } from 'react-redux'; const ArtistSearchResults = () => { const artistSearchResponse = useSelector(state => state.artistSearch.result); console.log('artist search data is:', artistSearchResponse); };
内容的提问来源于stack exchange,提问作者neil
相关产品推荐
相关产品推荐

