SYM's Tech Knowledge Index & Creation Records

「INPUT:OUTPUT=1:1以上」を掲げ構築する Tech Knowledge Stack and Index. by SYM@設計者足るため孤軍奮闘する IT Engineer.

Redux 基本

Redux 基本

ひとまず、storybook のチュートリアルに載っていた範囲+ α のみ

Redux とは

Flux ベースの state(状態)を容易に管理をするためのフレームワーク

refs:

Redux ストア

import { configureStore } from "@reduxjs/toolkit";

export const store = configureStore({
  reducer: {},
});
import { store } from "./app/store";
import { Provider } from "react-redux";

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);

configureStore を使用する場合、追加の入力は必要ないが、必要に応じて、RootState 型と Dispatch 型を抽出する必要がある。

ストア自体からこれらの型を推測することは、state slices を追加したりミドルウェア設定を変更したりすると、正しく更新されることを意味する。

アプリケーションで使用する際は、以下フックの作成推奨

  • useDispatch フック

useSelector の場合、毎回(state:RootState)と入力する必要はない。

  • useSelector フック

useDispatch の場合、既定の Dispatch 型は thunks を認識しません。正しく thunks を dispatch するには、thunk middleware types を含むストアから特定のカスタマイズされた AppDispatch 型を使用し、それを useDispatch と共に使用する必要がある。事前に型指定された useDispatch フックを追加すると、必要な場所に AppDispatch をインポートすることを忘れずに済む。

  • createSlice

初期状態、reducer 関数のオブジェクト、および 「スライス名」 を受け取り、reducer と状態に対応するアクションクリエーターとアクションタイプを自動的に生成する関数。

// app/sotre.ts
import { configureStore } from "@reduxjs/toolkit";
import { useDispatch, useSelector } from "react-redux";
import type { TypedUseSelectorHook } from "react-redux";
import type { RootState, AppDispatch } from "./store";

const TasksSlice = createSlice({
  name: "taskbox",
  initialState: TaskBoxData,
  reducers: {
    updateTaskState: (state, action) => {
      const { id, newTaskState } = action.payload;
      const task = state.tasks.findIndex((task) => task.id === id);
      if (task >= 0) {
        state.tasks[task].state = newTaskState;
      }
    },
  },
});

// Redux ストア
export const store = configureStore({
  reducer: {
    taskbox: TasksSlice.reducer,
  },
});

// ストア自体から`RootState`型と`AppDispatch`型を推測する
export type RootState = ReturnType<typeof store.getState>;
// 推定型: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch;

// 単純な`useDispatch`と`useSelector`の代わりにアプリ全体で使用する
export const useAppDispatch: () => AppDispatch = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
// 発行
const pinTask = (value) => {
  dispatch(updateTaskState({ id: value, newTaskState: "TASK_PINNED" }));
};
  • createAsyncThunk

Redux アクションタイプ文字列と promise を返すコールバック関数を受け取る関数。渡されたアクションタイププレフィックスに基づいて promise ライフサイクルアクションタイプを生成し、promise コールバックを実行し、返された promise に基づいてライフサイクルアクションをディスパッチする thunk アクションクリエーターを返す。

これにより、非同期要求ライフサイクルを処理するための標準的な推奨アプローチが抽象化されます。

import { userAPI } from "./userAPI";

const fetchUserById = createAsyncThunk(
  "users/fetchByIdStatus",
  async (userId: number, thunkAPI) => {
    const response = await userAPI.fetchById(userId);
    return response.data;
  }
);

const usersSlice = createSlice({
  name: "users",
  initialState,
  reducers: {
    // ry
  },
  extraReducers: (builder) => {
    // ここに追加のアクションタイプのレジューサを追加し、必要に応じてロード状態を処理します
    builder.addCase(fetchUserById.fulfilled, (state, action) => {
      state.entities.push(action.payload);
    });
  },
});

// Later, dispatch the thunk as needed in the app
dispatch(fetchUserById(123));