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

## 概要
Redux Tool Kit QueryのbaseQuery にAxiosを使った。
headersを追加する例が公式ドキュメントに載っておらず試行したメモ。
最初は`preparedHeaders`を記載しても反映されずに首をかしげていたが、custom query内で設定する必要があった。
よりスマートなサンプルなどあれば教えてほしい。

[ソースコード](https://github.com/hibohiboo/tomoshibi/tree/id/rtkqTest)

## 環境
- @reduxjs/toolkit: 1.8.2
- axios: 0.27.2

## 実装

```ts
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が適切に設定できていたら、２００が返る。

```ts
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`を自動生成しない。

```ts
- 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](https://redux-toolkit.js.org/rtk-query/usage/customizing-queries)
[RTKQ - overview](https://redux-toolkit.js.org/rtk-query/overview)
[Redux ToolitのRTK Queryについて](https://qiita.com/7tsuno/items/2301a35283db7cd54df9)
[RTKQueryの基本（設定〜使い方）](https://qiita.com/kana-wwib/items/2928c395608aa4318acf)
[github - redux -toolkit](https://github.com/reduxjs/redux-toolkit)
[github - axios](https://github.com/axios/axios)
[github - msw](https://github.com/mswjs/msw)