首先,我查看了Redux-Tools文档,但通过injecting endpointscode splitting没有找到这个问题的答案.我不知道这是否是一个错误,但我也会在Github上发布以供TK使用.

Problem:当您使用TEKMutations 并具有多个injectEndpoints时,GET(查询)的重新验证会多次触发.我有多个injectEndpoints,因为我想要分离我的每个端点.我看到的是,对于每个包含injectEndpoint的单独文件,TK会 for each 文件获取额外的信息.

Expected:当您触发TEKMutations 时,无论API中有多少个injectEndpoints,任何GET(查询)的重新验证都应仅触发1次.这是第一次引入TK时的行为.

Code: 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
})

Base Query.js base Query.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'
  ]
})

Post-Api.js 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

App.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-Tools、Material-UI、Ramda.我在这里使用jsonplaceholder API作为一个简单的例子,以便您可以轻松复制这个问题.

What is happening

  1. 当您查看网络选项卡时,您将获得posts comments端点的初始GET
  2. 单击"添加帖子"按钮
  3. POSTemits 到posts终点
  4. 网络选项卡向posts端点触发GET 3次
  5. 1 201
  6. 3 200 s GET,如果没有注入comments端点,则返回2 200 s GET.这意味着每注入一个端点,就会发生另外GET个端点

注: 我没有将reaction应用程序置于严格模式,因为这不会对最终结果产生任何影响.看起来每GET个人都在重新渲染App.js组件,但Redux Store不应该导致这个问题.在之前使用Redux和TEK的应用程序中,您可以轻松地像这样编写应用程序,并且永远不会看到您使用的每个Mutation都会触发多个GET.

问题图片:

  • Before button click Before Button Click

  • After button click After Button Click

推荐答案

即使您正在进行代码拆分,您仍然只有一个正在"扩展/增强"的API片段.

我几乎可以肯定您的问题是由添加实际上"复制"的API切片引起的,commentsApipostApi中的每一个都"扩展/增强"了基本baseQuery API切片.您只需 for each 基本查询添加一个API切片.无论您导入在store 中使用的API切片都应该已经将拆分的API切片注入其中.

示例:

Base Query.js base Query.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'
  ]
});

Post-Api.js postApi.js:导入baseQuery个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;

commentsApi.js:应该从postsApi.js导入增强的API切片,并输出另一个增强的API切片版本.

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;
import { configureStore } from '@reduxjs/toolkit';

// API
import baseQuery from 'api/commentsApi';

const reducer = {
  [baseQuery.reducerPath]: baseQuery.reducer,
};

const middleware = getDefaultMiddleware =>
  getDefaultMiddleware()
    .concat(baseQuery.middleware);

export const 店 = configureStore({
  middleware,
  reducer
});

替代

我之前通常做的是从拆分代码中输出just端点定义,并将它们注入到创建根baseQueryAPI切片的文件/组件中.

示例:

Base Query.js base Query.js

import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import { commentsApi } from 'api/commentsApi'
import { postApi } from 'api/postApi'

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'
  ]
});

Post-Api.js postApi.js


export const postApi = {
  endpoints: ({ mutation, query }) => ({
    addPost: mutation({
      invalidatesTags: ['posts'],
      query: ({ id }) => ({
        method: 'POST',
        url: `/posts`
      })
    }),
    getPosts: query({
      providesTags: ['posts'],
      query: () => `/posts`
    }),
  })
};

commentsApi.js

export const commentsApi = {
  endpoints: ({ mutation, query }) => ({
    getComments: query({
      providesTags: ['comments'],
      query: () => `/posts/1/comments`
    }),
  })
};

import { configureStore } from '@reduxjs/toolkit';

// API
import { baseQuery } from 'api/baseQuery';
import { commentsApi } from 'api/commentsApi';
import { postApi } from 'api/postApi';

const apiSlice = baseQuery
  .injectEndpoints(commentsApi)
  .injectEndpoints(postApi);

const reducer = {
  [apiSlice.reducerPath]: apiSlice.reducer,
}

const middleware = getDefaultMiddleware =>
  getDefaultMiddleware()
    .concat(apiSlice.middleware)

export const 店 = configureStore({
  middleware,
  reducer
});

export const {
  // ... all the generated hooks ...
} = apiSlice;

Javascript相关问答推荐

使用JavaScript重命名对象数组中的键

如何判断属于多个元素的属性是否具有多个值之一

Vega中的模运算符

InDesign—创建一个独立的窗口,在文档中进行更正时保持打开状态

未捕获错误:[]:getActivePinia()被调用,但没有活动Pinia.🍍""在调用app.use(pinia)之前,您是否try 使用store ?""

构造HTML表单以使用表单数据创建对象数组

无法检测卡片重叠状态的问题

Websocket错误—有一个或多个保留位开启:reserved1 = 1,reserved2 = 0,reserved3 = 0

当id匹配时对属性值求和并使用JavaScript返回结果

基于props 类型的不同props ,根据来自接口的值扩展类型

如何在JAVASCRIPT中合并两组对象并返回一些键

面对代码中的错误作为前端与后端的集成

将对象推送到数组会导致复制

AJAX POST在控制器中返回空(ASP.NET MVC)

React Refs不与高阶组件(HOC)中的动态生成组件一起工作

使用CEPRESS截取时,cy.Wait()在等待5000ms的第一个路由请求时超时

表单数据中未定义的数组键

如何将字符串拆分成单词并跟踪每个单词的索引(在原始字符串中)?

Firefox的绝对定位没有达到预期效果

如何为两条动态路由创建一个页面?