Scott

RTK query 9 months ago

react
5026个字符
共有117人围观

简介

RTK Query 是 Redux Toolkit 提供的一个强大的数据获取和缓存工具。它简化了与服务器进行数据交互的过程,减少了手动管理请求状态的复杂性。以下是一些常见的使用场景:

  • 数据获取和缓存:RTK Query 可以轻松地从服务器获取数据并自动缓存,以减少不必要的网络请求。
  • 自动重试失败请求:RTK Query 支持自动重试失败的请求,确保数据获取的可靠性。
  • 数据同步:当数据发生变化时,RTK Query 可以自动更新缓存中的数据,保持前端和后端数据的一致性。
  • 简化的状态管理:RTK Query 自动处理请求的状态(如加载中、成功、失败),减少了手动管理这些状态的代码量。
  • 优化的性能:通过缓存和去重请求,RTK Query 可以显著提高应用的性能。

需要注意的是RTK QUERY是可选的

RTK Query在typescript中的使用

在 TypeScript 中使用 RTK Query 需要一些额外的类型定义。以下是如何在 TypeScript 中使用 RTK Query 的基本步骤:

1,安装 Redux Toolkit 和 RTK Query:

npm install @reduxjs/toolkit react-redux

2, 创建 API Slice: 在 src/services 目录下创建一个 api.ts 文件,并定义一个 API slice。

// src/services/api.ts
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

interface Post {
  id: number;
  title: string;
  body: string;
}

export const api = createApi({
  reducerPath: 'api',
  baseQuery: fetchBaseQuery({ baseUrl: '/api' }),
  endpoints: (builder) => ({
    getPosts: builder.query<Post[], void>({
      query: () => 'posts',
    }),
  }),
});

export const { useGetPostsQuery } = api;

3, 配置 Redux Store: 在 src/app/store.ts中配置 Redux store,并添加 API slice 的 reducer。

// src/app/store.ts
import { configureStore } from '@reduxjs/toolkit';
import { setupListeners } from '@reduxjs/toolkit/query'
import { api } from '../services/api';

export const store = configureStore({
  reducer: {
    [api.reducerPath]: api.reducer,
  },
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware().concat(api.middleware),
});

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

// optional, but required for refetchOnFocus/refetchOnReconnect behaviors
// see `setupListeners` docs - takes an optional callback as the 2nd arg for customization
setupListeners(store.dispatch)

4, 提供 Redux Store: 在 src/index.tsx 中使用 Provider 提供 Redux store。

// src/index.tsx
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { store } from './app/store';
import App from './App';

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

5, 使用 API Slice: 在组件中使用 useGetPostsQuery 钩子来获取数据。

// src/components/Posts.tsx
import React from 'react';
import { useGetPostsQuery } from '../services/api';

const Posts: React.FC = () => {
  const { data, error, isLoading } = useGetPostsQuery();

  if (isLoading) return <>Loading...</>;
  if (error) return  <>Oh no, there was an error</>;

  return (
    <div>
      <h1>Posts</h1>
      <ul>
        {data?.map((post) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  );
};

export default Posts;

或者这样表示:

import React from 'react';
import { useGetPostsQuery } from '../services/api';

const Posts: React.FC = () => {
  const { data, error, isLoading } = useGetPostsQuery();

  return (
    <div>
      {isLoading ? (
        <>Loading...</>
      ) : error ? (
        <>Oh no, there was an error</>
      ) : (
        <>
          <h1>Posts</h1>
          <ul>
            {data?.map((post) => (
              <li key={post.id}>{post.title}</li>
            ))}
          </ul>
        </>
      )}
    </div>
  );
};

export default Posts;

6, 在应用中使用组件: 在 src/App.tsx 中导入并使用 Posts 组件。

// src/App.tsx
import React from 'react';
import Posts from './components/Posts';

const App: React.FC = () => {
  return (
    <div>
      <Posts />
    </div>
  );
};

export default App;

通过以上步骤,你就可以在 TypeScript 中使用 RTK Query 来进行数据获取和缓存。

如何添加自定义header

还是以上面的例子为例,只需要在fetchBaseQuery中添加header即可

// src/services/api.ts
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';

interface Post {
  id: number;
  title: string;
  body: string;
}

export const api = createApi({
  reducerPath: 'api',
  baseQuery: fetchBaseQuery({
    baseUrl: '/api',
    prepareHeaders: (headers) => {
      headers.set('authorization', `Bearer YOUR_TOKEN_HERE`);
      return headers;
    },
  }),
  endpoints: (builder) => ({
    getPosts: builder.query<Post[], void>({
      query: () => 'posts',
    }),
  }),
});

export const { useGetPostsQuery } = api;

但是每个api都这么写显然有些麻烦,我们可以把baseQuery提出来:

prepareHeaders 用于在发出任何请求之前设置自定义头 X-Custom-Header

我们只将 ‘X-Custom-Header’ 和 ‘your-custom-header-value’ 替换成自己所需的header即可

import { fetchBaseQuery } from '@reduxjs/toolkit/query/react';

const baseQuery = fetchBaseQuery({
  baseUrl: 'https://api.your-really-great-app.com/v1/',
  prepareHeaders: (headers, { getState }) => {
    // Add your custom header here
    headers.set('X-Custom-Header', 'your-custom-header-value');
    return headers;
  },
});

export const apiSlice = createApi({
  reducerPath: 'api',
  baseQuery: baseQuery,
  endpoints: (builder) => ({
    getSomething: builder.query({
      query: () => '/something',
    }),
  }),
});

export const { useGetSomethingQuery } = apiSlice;