Redux Toolkit TypeScript クイックスタート
- Redux Toolkit と React-Redux を TypeScript で設定および使用する方法
- React の知識 Hooks
- Redux の用語と概念 の理解
- TypeScript の構文と概念の理解
はじめに
Redux Toolkit TypeScript クイックスタートチュートリアルへようこそ! このチュートリアルでは、TypeScript を Redux Toolkit と React-Redux と共に使用する簡単な方法を紹介します。
このページでは、TypeScript の設定方法のみに焦点を当てています。Redux とは何か、どのように機能するか、Redux Toolkit の使用方法の完全な例については、「チュートリアルインデックス」ページにリンクされているチュートリアルを参照してください。チュートリアルインデックスページにリンクされているチュートリアルを参照してください。
Redux Toolkit は既に TypeScript で記述されているため、その TS 型定義は組み込まれています。
React Redux もバージョン 8 から TypeScript で記述されており、独自の型定義も含まれています。
Create-React-App 用の Redux+TS テンプレート には、これらのパターンが既に構成された動作例が付属しています。
プロジェクトの設定
ルート状態とディスパッチ型の定義
Redux Toolkit の configureStore
API には、追加の型付けは必要ありません。ただし、RootState
型と Dispatch
型は、必要に応じて参照できるように抽出する必要があります。ストア自体からこれらの型を推論することで、状態スライスを追加したり、ミドルウェアの設定を変更したりするときに、正しく更新されます。
これらは型なので、app/store.ts
などのストア設定ファイルから直接エクスポートし、他のファイルに直接インポートしても安全です。
import { configureStore } from '@reduxjs/toolkit'
// ...
export const store = configureStore({
reducer: {
posts: postsReducer,
comments: commentsReducer,
users: usersReducer
}
})
// Infer the `RootState` and `AppDispatch` types from the store itself
export type RootState = ReturnType<typeof store.getState>
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch
型付きフックの定義
RootState
と AppDispatch
型を各コンポーネントにインポートすることもできますが、アプリケーションで使用するための useDispatch
と useSelector
フックの型付きバージョンを作成する方が優れています。これはいくつかの理由で重要です。
useSelector
の場合、毎回(state: RootState)
を入力する必要がなくなります。useDispatch
の場合、デフォルトのDispatch
型は thunk を認識しません。thunk を正しくディスパッチするには、thunk ミドルウェアの型を含むストアから特定のカスタマイズされたAppDispatch
型を使用し、それをuseDispatch
と共に使用する必要があります。事前に型付けされたuseDispatch
フックを追加することで、AppDispatch
を必要な場所でインポートすることを忘れるのを防ぎます。
これらは実際の変数であり、型ではないため、ストア設定ファイルではなく、app/hooks.ts
などの別のファイルで定義することが重要です。これにより、フックを使用する必要があるコンポーネントファイルにインポートし、循環インポート依存関係の問題を回避できます。
import { useDispatch, useSelector } from 'react-redux'
import type { AppDispatch, RootState } from './store'
// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch = useDispatch.withTypes<AppDispatch>()
export const useAppSelector = useSelector.withTypes<RootState>()
アプリケーションの使用
スライス状態とアクション型の定義
各スライスファイルは、初期状態値の型を定義する必要があります。これにより、createSlice
は各ケースリデューサーで state
の型を正しく推論できます。
生成されたすべてのアクションは、Redux Toolkit の PayloadAction<T>
型を使用して定義する必要があります。この型は、action.payload
フィールドの型をジェネリック引数として受け取ります。
ストアファイルから RootState
型を安全にインポートできます。これは循環インポートですが、TypeScript コンパイラは型の処理を正しく行うことができます。これは、セレクター関数を記述するなど、ユースケースに必要な場合があります。
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import type { RootState } from '../../app/store'
// Define a type for the slice state
export interface CounterState {
value: number
}
// Define the initial state using that type
const initialState: CounterState = {
value: 0
}
export const counterSlice = createSlice({
name: 'counter',
// `createSlice` will infer the state type from the `initialState` argument
initialState,
reducers: {
increment: state => {
state.value += 1
},
decrement: state => {
state.value -= 1
},
// Use the PayloadAction type to declare the contents of `action.payload`
incrementByAmount: (state, action: PayloadAction<number>) => {
state.value += action.payload
}
}
})
export const { increment, decrement, incrementByAmount } = counterSlice.actions
// Other code such as selectors can use the imported `RootState` type
export const selectCount = (state: RootState) => state.counter.value
export default counterSlice.reducer
生成されたアクションクリエーターは、リデューサーに指定した PayloadAction<T>
型に基づいて、payload
引数を正しく受け入れるように型付けされます。たとえば、incrementByAmount
は引数として number
を必要とします。
場合によっては、TypeScript が初期状態の型を不必要に厳しくする可能性があります。その場合は、変数の型を宣言する代わりに、as
を使用して初期状態をキャストすることで回避できます。
// Workaround: cast state instead of declaring variable type
const initialState = {
value: 0
} as CounterState
コンポーネントでの型付きフックの使用
コンポーネントファイルでは、React-Redux から標準のフックではなく、事前に型付けされたフックをインポートします。
import React from 'react'
import { useAppSelector, useAppDispatch } from 'app/hooks'
import { decrement, increment } from './counterSlice'
export function Counter() {
// The `state` arg is correctly typed as `RootState` already
const count = useAppSelector(state => state.counter.value)
const dispatch = useAppDispatch()
// omit rendering logic
}
完全なカウンターアプリの例
実行可能な CodeSandbox として、完全な TS カウンターアプリケーションを次に示します。
次のステップ
完全な「Redux Essentials」チュートリアル を参照することをお勧めします。これには、Redux Toolkit に含まれるすべての主要な要素、それらが解決する問題、およびそれらを使用して現実世界のアプリケーションを構築する方法が説明されています。
「Redux 基礎」チュートリアル も読むことをお勧めします。これにより、Redux の動作方法、Redux Toolkit の機能、および Redux Toolkit の正しい使用方法を完全に理解できます。
最後に、「TypeScript を使用した使用方法」ページ を参照して、TypeScript で Redux Toolkit の API を使用する詳細を確認してください。