作为序言,我查看了 Redux-Toolkit 文档,但没有通过 注入端点 和 代码分割 找到此问题的答案。我不知道这是否是一个错误,但也会在 RTK 的 Github 上发布。
问题:当您使用 RTK 突变并具有多个
injectEndpoints
时,会多次触发 GET(查询)的重新验证。我有多个injectEndpoints,因为我想分离每个端点。我看到的是对于每个带有 injectEndpoint
的单独文件,RTK 正在为每个文件获取额外的内容。
预期:当您触发 RTK 突变时,任何 GET(查询)的重新验证都应该只触发 1 次,无论 API 中有多少个
injectEndpoints
。这是 RTK 首次引入时的行为。
代码: store.js
import { configureStore } from '@reduxjs/toolkit'
// API
import { baseQuery } from 'api/baseQuery'
import { commentsApi } from 'api/commentsApi'
import { postApi } from 'api/postApi'
const reducer = {
[baseQuery.reducerPath]: baseQuery.reducer,
[commentsApi.reducerPath]: commentsApi.reducer,
[postApi.reducerPath]: postApi.reducer
}
const middleware = getDefaultMiddleware =>
getDefaultMiddleware()
.concat(baseQuery.middleware)
.concat(commentsApi.middleware)
.concat(postApi.middleware)
export const store = configureStore({
middleware,
reducer
})
baseQuery.js
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
export const baseQuery = createApi({
baseQuery: fetchBaseQuery({
baseUrl: 'https://jsonplaceholder.typicode.com',
prepareHeaders: headers => {
headers.set('Accept', 'application/json')
return headers
}
}),
endpoints: () => ({}),
reducerPath: 'api',
tagTypes: [
'comments',
'posts'
]
})
postApi.js
import { baseQuery } from './baseQuery'
export const postApi = baseQuery.injectEndpoints({
endpoints: ({ mutation, query }) => ({
addPost: mutation({
invalidatesTags: ['posts'],
query: ({ id }) => ({
method: 'POST',
url: `/posts`
})
}),
getPosts: query({
providesTags: ['posts'],
query: () => `/posts`
}),
})
})
export const {
useAddPostMutation,
useGetPostsQuery
} = postApi
commentsApi.js
import { baseQuery } from './baseQuery'
export const commentsApi = baseQuery.injectEndpoints({
endpoints: ({ mutation, query }) => ({
getComments: query({
providesTags: ['comments'],
query: () => `/posts/1/comments`
}),
})
})
export const {
useGetCommentsQuery
} = commentsApi
应用程序.js
import { Button, Stack, Typography } from '@mui/material'
import ChevronLeftRoundedIcon from '@mui/icons-material/ChevronLeftRounded'
import { useAddPostMutation, useGetPostsQuery } from 'api/postApi'
import { useGetCommentsQuery } from 'api/commentsApi'
const App = () => {
const { data = [] } = useGetPostsQuery()
const { data: comments = []} = useGetCommentsQuery()
const [addPost] = useAddPostMutation()
console.log('comments', comments)
return (
<>
<Button
onClick={addPost}
startIcon={<ChevronLeftRoundedIcon />}
>
Add Post
</Button>
<Stack
spacing={3}
sx={{
alignItems: 'center',
justifyContent: 'center',
px: 3
}}
>
<Typography>
List of Posts
</Typography>
{data.map(({ id, title }) => (
<Typography key={id} variant='body2'>
{title}
</Typography>
))}
</Stack>
</>
)
}
export default App
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { Provider } from 'react-redux'
import { store } from 'store/store';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<Provider store={store}>
<App />
</Provider>
);
这里唯一的依赖项是 Redux、Redux-Toolkit、Material-UI、Ramda。我在这里使用
jsonplaceholder API
作为一个简单的示例,以便您可以轻松地复制此问题。
发生了什么事
GET
和 posts
端点的初始 comments
POST
发射到 posts
端点GET
端点触发 3 次1 201 posts
POST
GET
端点,这将返回 2 200s comments
。这意味着对于每个注入的端点,都会发生额外的GET
发生
GET
都在重新渲染 App.js 组件,但 Redux Store 不应该导致此问题。在以前使用 Redux 和 RTK 的应用程序中,您可以轻松地像这样编写应用程序,并且永远不会看到为您使用的每个 Mutation 触发多个
GET
。问题图片:
我几乎可以肯定您的问题是由于添加了有效的“重复”API 切片而引起的,每个
GET
和
commentsApi
“扩展/增强”了基础 postApi
API 切片。您只需为每个基本查询添加一个 API 切片。无论您导入以在商店中使用什么 API 切片,都应该已经将拆分的 API 切片注入其中。示例:
baseQuery.js
baseQuery
postApi.js:导入
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
export const baseQuery = createApi({
baseQuery: fetchBaseQuery({
baseUrl: 'https://jsonplaceholder.typicode.com',
prepareHeaders: headers => {
headers.set('Accept', 'application/json');
return headers;
}
}),
endpoints: () => ({}),
reducerPath: 'api',
tagTypes: [
'comments',
'posts'
]
});
API 切片,并导出增强版本。
baseQuery
commentsApi.js:应从 postsApi.js 导入增强型 API 切片,并导出另一个增强型 API 切片版本。
import { baseQuery } from './baseQuery';
const enhancedBaseQuery = baseQuery.injectEndpoints({
endpoints: ({ mutation, query }) => ({
addPost: mutation({
invalidatesTags: ['posts'],
query: ({ id }) => ({
method: 'POST',
url: `/posts`
})
}),
getPosts: query({
providesTags: ['posts'],
query: () => `/posts`
}),
})
})
export const {
useAddPostMutation,
useGetPostsQuery
} = enhancedBaseQuery;
export default enhancedBaseQuery;
import baseQuery from 'api/postApi';
const enhancedBaseQuery = baseQuery.injectEndpoints({
endpoints: ({ mutation, query }) => ({
getComments: query({
providesTags: ['comments'],
query: () => `/posts/1/comments`
}),
})
});
export const {
useGetCommentsQuery
} = BaseQuery;
export default BaseQuery;