LoginSignup
0
0

More than 1 year has passed since last update.

Redux Tool Kit QueryのbaseQuery にAxiosを使ってHeadersを設定したメモ

Posted at

概要

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のほうのcreateApiuseHogeQueryを自動生成しない。

- 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

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0