Redux-Toolkit Query中的extra和extraoptions有什么用?在使用查询& queryFn时如何填充它们?

bpzcxfmw  于 11个月前  发布在  其他
关注(0)|答案(2)|浏览(127)

我只是好奇知道填充extraextraOptions的方法,以及参数必须按顺序传递的位置,以便它们可以被填充,然后可以用于创建一些基于条件的场景。queryFn本身用于在Redux-Toolkit(RTK)查询(RTKQ)中创建自定义查询函数。

import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";

const shiprocketApiSlice = createApi({
  baseQuery: fetchBaseQuery({
    baseUrl: "https://apiv2.shiprocket.in/v1/external",
    prepareHeaders: (headers, { getState, extra, type, endpoint }) => {
      const token =
        "...someToken";
      token && headers.set("authorization", `Bearer ${token}`);
      console.log(
        "the extra value of the ====> ",
        extra,
        getState(),
        type,
        endpoint,
        headers
      );
      return headers;
    },
  }),
  endpoints: (builder) => ({
    updateUser: builder.mutation({
      query: (user) => {
        return {
          url: `/users/${user.queryArg}`,
          headers: {
            "X-Scope": "1234567890",
          },
        };
      },
    }),
    createOrderShiprocket: builder.mutation({
      queryFn: async (args, api, extraOptions, baseQuery) => {
        console.log(
          "printin all the agrs of the qrfn to see what exactly it is ===> ",
          args,
          api,
          "extraoptions==>",
          extraOptions,
          "base==>",
          baseQuery
        );
        
        const response = await baseQuery(args, api, extraOptions);
        console.log("the response ==>", response);
        return { error: { message: "error occured" } };
      },
    }),
  }),
});

export const { useCreateOrderShiprocketMutation, useUpdateUserMutation } =
  shiprocketApiSlice;

字符串
我用了这个文件里的钩子

"use client";

import React from "react";
import {
  useCreateOrderShiprocketMutation,
  useUpdateUserMutation,
} from "@/store/features/shiprocket/shiprocketApiSlice";

const TestFolderPage = () => {
  const [createOrderShiprocket, { data: TheOrderList }] =
    useCreateOrderShiprocketMutation();

  const [updateUser, { data: updatedData }] = useUpdateUserMutation();
  const handleClick = () => {
    console.log("the click");
    updateUser({ queryArg: 12344 });
    createOrderShiprocket({ userId: 123 });
  };
  return <div onClick={handleClick}>TestFolderPage</div>;
};

export default TestFolderPage;

kupeojn6

kupeojn61#

Redux-Toolkit(RTK)query(RTKQ)中extraextraOptions有什么用?

extra第一代

作为thunk.extraArgument提供给configureStore getDefaultMiddleware选项。
BaseQueryApi

export interface BaseQueryApi {
  signal: AbortSignal
  abort: (reason?: string) => void
  dispatch: ThunkDispatch<any, any, any>
  getState: () => unknown
  extra: unknown             // <-- specified thunk.extraArgument
  endpoint: string
  type: 'query' | 'mutation'
  forced?: boolean
}

字符串
extra是配置Redux存储时与Redux-Toolkit的Thunk中间件一起使用的额外参数。有关详细信息,请参阅自定义包含的中间件。基本示例如下:

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

const store = configureStore({
  reducer,
  middleware: (getDefaultMiddleware) =>
    getDefaultMiddleware({
      thunk: {
        extraArgument: /* whatever value you need here */,
      },
    }),
});


这个extraArgument暴露在createAsyncThunk操作的thunkApi中,显然是Redux-Toolkit Query的prepareHeaders函数签名的一部分。

type prepareHeaders = (
  headers: Headers,
  api: {
    getState: () => unknown
    extra: unknown              // <-- the extra arg from store
    endpoint: string
    type: 'query' | 'mutation'
    forced: boolean | undefined
  }
) => Headers | void

extraOptions

参见文档中的extraOptions
很简单,extraOptions是一个可选对象,作为第三个参数传递给提供的baseQuery函数,例如,在代码示例中,fetchBaseQuery返回的基本查询函数。参见fetchBaseQuery签名。

type FetchBaseQuery = (
  args: FetchBaseQueryArgs
) => (
  args: string | FetchArgs,
  api: BaseQueryApi,
  extraOptions: ExtraOptions // <-- third arg, the extra options
) => FetchBaseQueryResult


使用queryqueryFn时如何填充它们?
我已经在上面介绍了在配置存储时在哪里以及如何指定/添加extra值。extraOptions可以为每个端点指定。
范例:

updateUser: builder.mutation({
  query: (user) => ({
    url: `/users/${user.queryArg}`,
    headers: {
      'X-Scope': '1234567890',
    },
  }),
  extraOptions: {
    // any custom extra options/properties you want to pass to the base query
  },
}),
createOrderShiprocket: builder.mutation({
  queryFn: async (args, api, extraOptions, baseQuery) => {     // <-- accessed here
    ...
    
    const response = await baseQuery(args, api, extraOptions); // <-- passed through

    ...
  },
  extraOptions: {
    // any custom extra options/properties you want to pass to the base query
  },
}),


在需要定制基本查询函数之前,这一点并不特别有用。
例如,一个相当简单的定制就是为失败的查询添加自动重试。

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

const baseQuery = retry(
  fetchBaseQuery({
    baseUrl: "https://apiv2.shiprocket.in/v1/external",
    prepareHeaders: (headers, { getState, extra, type, endpoint }) => {
      const token = "...someToken";

      token && headers.set("authorization", `Bearer ${token}`);
      
      return headers;
    },
  }),
  {
    maxRetries: 5,
  },
);
const shiprocketApiSlice = createApi({
  baseQuery, // <-- 5 retries by default
  endpoints: (builder) => ({
    updateUser: builder.mutation({
      query: (user) => ({
        url: `/users/${user.queryArg}`,
        headers: {
          'X-Scope': '1234567890',
        },
      }),
    }),
    createOrderShiprocket: builder.mutation({
      queryFn: async (args, api, extraOptions, baseQuery) => {
        ...

        const response = await baseQuery(args, api, extraOptions);

        ...
      },
      extraOptions: {
        maxRetries: 8 // <-- override default 5
      },
    }),
  }),
});

的字符串
这完全取决于您和您的应用的具体用例,以及需要哪些extraextraOptions是相关的和/或有用的。

vngu2lb8

vngu2lb82#

修改fetchBaseQuery使用extra

目前,prepareHeaders中的extra参数没有被使用,因为它没有在任何地方设置。如果你想使用它,你需要在调用fetchBaseQuery时为extra提供一个值。但是,通常extra用于更高级的场景,比如当你有一个中间件设置它时。

queryFn中传递和使用extraOptions

为了演示如何传递和使用extraOptions,我将修改createOrderShiprocket在组件中的用法。

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

const shiprocketApiSlice = createApi({
  baseQuery: fetchBaseQuery({
    baseUrl: 'https://apiv2.shiprocket.in/v1/external',
    prepareHeaders: (headers, { getState, extra, type, endpoint }) => {
      const token = '...someToken';
      token && headers.set('authorization', `Bearer ${token}`);
      console.log('the extra value of the ====> ', extra, getState(), type, endpoint, headers);
      return headers;
    },
  }),
  endpoints: (builder) => ({
    updateUser: builder.mutation({
      query: (user) => ({
        url: `/users/${user.queryArg}`,
        headers: {
          'X-Scope': '1234567890',
        },
      }),
    }),

    createOrderShiprocket: builder.mutation({
      queryFn: async (args, api, extraOptions, baseQuery) => {
        console.log(
          'printin all the agrs of the qrfn to see what exactly it is ===> ',
          args,
          api,
          'extraoptions==>',
          extraOptions,
          'base==>',
          baseQuery
        );

        // Use extraOptions here for conditional logic
        if (extraOptions.someCondition) {
          // Custom handling based on extraOptions
        }

        const response = await baseQuery(args, api, extraOptions);
        console.log('the response ==>', response);
        return { error: { message: 'error occured' } };
      },
    }),
  }),
});

export const { useCreateOrderShiprocketMutation, useUpdateUserMutation } = shiprocketApiSlice;

字符串
然后:

import React from 'react';
import {
  useCreateOrderShiprocketMutation,
  useUpdateUserMutation,
} from '@/store/features/shiprocket/shiprocketApiSlice';

const TestFolderPage = () => {
  const [createOrderShiprocket, { data: TheOrderList }] = useCreateOrderShiprocketMutation();
  const [updateUser, { data: updatedData }] = useUpdateUserMutation();

  const handleClick = () => {
    console.log('the click');
    updateUser({ queryArg: 12344 });
    createOrderShiprocket({ userId: 123, extraOption: 'someValue' }); // Passing extraOption here
  };

  return <div onClick={handleClick}>TestFolderPage</div>;
};

export default TestFolderPage;

相关问题