Redux Toolkitがすごい便利だった
画面遷移しても状態保存しておこうと思い、再度reduxを見直していたが、これを見つけてちょっと感動した。
reduxの構成にしたい人はこれ入れておくとよさそう。
action, reducer, selectorの記述が少ない
reduxは何と言ってもコードの記述量が増えるのがめんどくさいのだが、とてもスマートに書ける。
import { createSlice, PayloadAction } from '@reduxjs/toolkit' import { CourtDoc } from 'models/court' import type { RootState } from 'store' type Mode = 'text' | 'location' type Geo = { lat: number lng: number } interface HomeState { mode: Mode zoom: number center: Geo courts?: CourtDoc[] } const initialState: HomeState = { mode: 'text', zoom: 11, center: { lat: 35.681236, lng: 139.767125 }, } export const homeSlice = createSlice({ name: 'home', initialState, reducers: { changeMode: (state, action: PayloadAction<Mode>) => { state.mode = action.payload }, changeZoom: (state, action: PayloadAction<number>) => { state.zoom = action.payload }, changeCenter: (state, action: PayloadAction<Geo>) => { state.center = action.payload }, }, }) export const { changeMode, changeZoom, changeCenter } = homeSlice.actions export const selectMode = (state: RootState): Mode => state.home.mode export const selectZoom = (state: RootState): number => state.home.zoom export const selectCenter = (state: RootState): Geo => state.home.center export const selectCourtDocs = (state: RootState): CourtDoc[] | undefined => state.home.courts export default homeSlice.reducer
actionのstringを自分で書かなくても、 createSlice
のname
と関数名から自動でいい感じに生成してくれる。
reducers
の書き換えをしてもglobalに影響が出ないようになっている。
reselect
まだやってないけど createSelector
でSelectorを作ると reselect
が使われてパフォーマンス上がる模様。
createSelector | Redux Toolkit
TypeScript対応
型がちゃんと付く。
フラグ一個でredux-devtools-extensionがつく
export const store = configureStore({ reducer: { firebase: firebaseReducer, firestore: firestoreReducer, home: HomeReducer, }, devTools: true, // <- これだけ })
副作用の対応
前述のcreateSlice
のところで、
import { createAsyncThunk, ... } from '@reduxjs/toolkit' import { search } from 'models/search' ... export const searchByText = createAsyncThunk( 'home/searchByText', async (params: { text: string; hits: number }) => { const courtDocs = await search(params.text, params.hits) return courtDocs } ) export const homeSlice = createSlice({ ..., extraReducers: { [searchByText.fulfilled.type]: ( state, action: PayloadAction<CourtDoc[]> ) => { state.courts = action.payload }, }, }) ... export default homeSlice.reducer
これでいい。
すごい便利だ...。まだかじっただけなので、もうちょっと調べる。