概要
Redux Tool Kit QueryのbaseQuery にAxiosを使った。
headersを追加する例が公式ドキュメントに載っておらず試行したメモ。
最初はpreparedHeaders
を記載しても反映されずに首をかしげていたが、custom query内で設定する必要があった。
よりスマートなサンプルなどあれば教えてほしい。
環境
- @reduxjs/toolkit: 1.8.2
- axios: 0.27.2
実装
import { FetchBaseQueryArgs } from '@reduxjs/toolkit/dist/query/fetchBaseQuery'
import { BaseQueryFn } from '@reduxjs/toolkit/query'
import { createApi } from '@reduxjs/toolkit/query/react'
import axios, { AxiosRequestConfig, AxiosError } from 'axios'
type AxiosParams = {
url: string
method: AxiosRequestConfig['method']
data?: AxiosRequestConfig['data']
params?: AxiosRequestConfig['params']
}
const client = axios.create()
const axiosBaseQuery =
(
{ baseUrl, prepareHeaders }: FetchBaseQueryArgs,
): BaseQueryFn<AxiosParams, unknown, unknown> =>
async ({ url, method, data, params }, api) => {
try {
const preparedHeaders =
prepareHeaders == null
? new Headers({})
: await prepareHeaders(new Headers({}), api)
// AxiosのheadersはHeadersクラスではなく、単純なオブジェクトを期待しているので変換
const headers: Record<string, string> = {}
for (const [key, value] of preparedHeaders.entries()) {
headers[key] = value
}
const result = await client({
url: baseUrl + url,
method,
data,
params,
headers,
})
return { data: result.data }
} catch (axiosError) {
const err = axiosError as AxiosError
return {
error: {
status: err.response?.status,
data: err.response?.data || err.message,
},
}
}
}
export const api = createApi({
reducerPath: 'api',
baseQuery: axiosBaseQuery({
baseUrl: 'http://localhost:3000/',
prepareHeaders: (headers, api) => {
api.getState() // StoreのStateにアクセスする場合は第二引数から取得できる
headers.set('x-api-key', 'todo')
return headers
},
}),
endpoints: (builder) => ({
getUsersWithAUth: builder.query<
{ date: string; value: number; user: string }[],
void
>({
query: () => ({
url: 'get-value-with-auth',
method: 'GET',
}),
}),
}),
})
export const { useGetValueQuery, useGetUsersValueQuery } = api
チェック
mswを利用して確認を行った。headersが適切に設定できていたら、200が返る。
import { rest } from 'msw'
const domain = 'http://localhost:3000/'
export const handlers = [
rest.get(`${domain}get-value-with-auth`, (req, res, ctx) => {
if (!req.headers.get('x-api-key')) {
return res(ctx.status(401), ctx.json(req))
}
return res(ctx.status(200), ctx.json(req))
}),
]
余談
createApi
は@reduxjs/toolkit/query
にも@reduxjs/toolkit/query/react
にもいて、
importを間違えて少しハマった。
@reduxjs/toolkit/query
のほうのcreateApi
はuseHogeQuery
を自動生成しない。
- import { createApi } from '@reduxjs/toolkit/query'
+ import { createApi } from '@reduxjs/toolkit/query/react'
export const api = createApi({
//省略
});
export const { useGetValueQuery, useGetUsersValueQuery } = api
参考
RTKQ - Customizing queries
RTKQ - overview
Redux ToolitのRTK Queryについて
RTKQueryの基本(設定〜使い方)
github - redux -toolkit
github - axios
github - msw