[react] redux-toolkit with typescript

13823 ワード

redux-toolkit公式ドキュメントこれは個人の学習に関する文章です.
  • 勉強
    Redux ToolkitとReact-ReduxをType Script
  • に設定する方法
    プロジェクトの設定
    RootStateとDispatchタイプの定義configureStore他の入力は必要ありません.ただし、参照のために必要に応じてRootStateタイプおよびDispatchタイプを抽出することができる.これらのタイプは、ショップ自体から推定すると、より多くのステータスシートを追加したり、ミドルウェアの設定を変更したりしたときに正しく更新されます.
    これらは、app/store.tsなどのショップ設定ファイルから直接エクスポートされ、他のファイルに直接インポートされます.
    app/store.ts
    import { configureStore, ThunkAction, Action } from '@reduxjs/toolkit';
    import counterReducer from '../features/counter/counterSlice';
    
    export const store = configureStore({
      reducer: {
        counter: counterReducer,
      },
    });
    
    export type AppDispatch = typeof store.dispatch; // Type to access dispatch
    export type RootState = ReturnType<typeof store.getState>; // A global type to access reducers types 
    export type AppThunk<ReturnType = void> = ThunkAction<
      ReturnType,
      RootState,
      unknown,
      Action<string>
    >;
    タイプ付きフックの定義
    各コンポーネントにRootStateまたはAppDispatchタイプをインポートできますが、useDispatchまたはuseSelectorhookタイプのアプリケーションバージョンを作成することをお勧めします.これはいくつかの原因が重要です.
  • useSelector=>(state: RootState)|を入力する必要はありません.
  • useDispatch=>デフォルトDispatchタイプはthunkを知りません.thunkを正しく派遣するには、ショップはthunkミドルウェアタイプを含む特定のカスタムAppDispatchタイプを使用し、useDispatchとともに書き込む必要があります.
    予め入力されたuseDispatchhookが追加されている場合は、AppDispatchを必要な場所にインポートすることを忘れません.
  • これはタイプではなく実際の変数であるため、app/hooks.tsなどの個別のファイルで定義することが重要です.
    これにより、Hookを使用する必要があるすべての構成部品ファイルにインポートし、依存関係の問題を回避できます.
    app/hooks.ts
    import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
    import type { RootState, AppDispatch } from './store'
    
    // Use throughout your app instead of plain `useDispatch` and `useSelector`
    export const useAppDispatch = () => useDispatch<AppDispatch>()
    export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector
    アプリケーションの使用
    sliceステータスとアクションタイプの定義
    各スライスファイルは、createSliceが各リーダからstateを正確に推定できるように、初期状態値のタイプを定義しなければならない.
    作成されたすべてのアクションは、JENICパラメータとしてフィールドを使用するRedux Toolkitのaction.payloadタイプ定義を使用する必要があります.
    ショップファイルからPayloadAction<T>タイプを安全にインポートできます.ループインポートですが、タイプスクリプトコンパイラはタイプを正しく処理できます.使用例では、セレクタ関数を作成する必要がある場合があります.
    counterSlice.ts
    import { createSlice, PayloadAction } from '@reduxjs/toolkit'
    import type { RootState } from '../../app/store'
    
    // Define a type for the slice state 
    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`
        //  PayloadAction 타입을 사용하여 `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
    RootStateタイプに従って、PayloadAction<T>パラメータの入力を許可するためにreduceに正しく入力され、提供されている.
    例えば、パラメータpayloadとしてincrementByAmountが必要である.
    場合によっては、TypeScriptが初期状態を必要としないタイプが表示される場合があります.この場合、number鋳造初期状態を使用して、変数タイプを宣言することなく、問題を解決することができる.
    構成部品にタイプ化されたフックを使用する
    構成部品ファイルに、React-Reduxの標準フックではなく、プリタイプのフックをインポートします.
    features/counter/Counter.tsx
    import React, { useState } 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 렌더링 로직 생략
    }