Next.jsでRedux-toolkitをコピペだけでセットアップ

半年ほど前に学んだRedux

当初は何をやっているのかさっぱり分からなかった

それでも諦めずにReduxと向き合い、今ではRedux無しでは開発できない体となってしまった。

ただ、毎回環境構築をして思うことがある。

「Reduxの環境構築面倒くさい。。。」

そこで、暇な時間にネットサーフィンをしていると、気になるパッケージを見つけた。

それが**Redux-toolkit**

今では、公式もRedux-toolkitを使うことをおすすめすると発表するほど素晴らしいパッケージ

Reduxのmiddlewareなどの複雑な環境構築を全て自動でやってくれる

そんなRedux-toolkitを更に、コピだけで環境構築を行えるようにします！！！！

特に細かい説明はしませんのでご了承下さい。

# パッケージのインストール

```bash
npm i @reduxjs/toolkit react-redux redux-persist
npm i -D @types/react-redux
```

# storeフォルダの作成

プロジェクト直下に``store``フォルダを作成してください。

また、他のフレームワークを使用している場合は公式ドキュメントにReduxをどこに格納すれば良いか書いてあると思うので、そちらを参照してください。

# ストアの作成

先ほど作成した storeディレクトリに``index.ts``を作成してください。

そして以下をコピペ

※ userSliceはこのあと作成するので消さないでください。

```/store/index.ts
import {
    configureStore,
    getDefaultMiddleware,
    combineReducers,
    EnhancedStore,
} from '@reduxjs/toolkit'
import { loadingSlice } from './loading'
import {
    persistReducer,
    FLUSH,
    REHYDRATE,
    PAUSE,
    PERSIST,
    PURGE,
    REGISTER,
} from 'redux-persist'
import createWebStorage from 'redux-persist/lib/storage/createWebStorage'
import { userSlice } from './user'

// https://github.com/vercel/next.js/discussions/15687#discussioncomment-45319
const createNoopStorage = () => {
    return {
        getItem(_key) {
            return Promise.resolve(null)
        },
        setItem(_key, value) {
            return Promise.resolve(value)
        },
        removeItem(_key) {
            return Promise.resolve()
        },
    }
}
const storage =
    typeof window !== 'undefined'
        ? createWebStorage('local')
        : createNoopStorage()

const rootReducer = combineReducers({
    user: userSlice.reducer,
})


const persistConfig = {
    key: 'redux-toolkit-example',
    version: 1,
    storage,
}
const persistedReducer = persistReducer(persistConfig, rootReducer)

export const useStore = configureStore({
    reducer: persistedReducer,
    middleware: getDefaultMiddleware({
        serializableCheck: {
            ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
        },
    }),
})

export type RootState = ReturnType<typeof rootReducer>
export type AppDispatch = typeof useStore.dispatch
```

``_app.tsx``でReduxのプロバイダーでラッピングしてあげます。

```/pages/_app.tsx
import { AppProps } from "next/app";
import { Provider } from "react-redux";
import { persistStore } from "redux-persist";
import { PersistGate } from "redux-persist/integration/react";
import { store } from "../store";

const CustomApp = ({ Component, pageProps }: AppProps): JSX.Element => {
    const persistor = persistStore(store);

    return (
        <Provider store={store}>
            <PersistGate persistor={persistor}>
                // コンポーネント
            </PersistGate>
        </Provider>
    );
};

export default CustomApp;

```


#ユーザーのストアを作成

これでReduxを使える環境は整ったので、一例としてユーザーのストアを作成してみましょう。

```/store/user/index.ts
import { createSlice, PayloadAction } from "@reduxjs/toolkit";

export type User = {
    username: string;
    email: string;
};

export type UserState = User;

export type UpdateUserPayload = User;

// 初期値
const initialState: UserState = {
    username: "Next.js",
    email: "next@gmail.com"
};

export type UpdateUser = {
    username: string;
    email: string
};

export const userSlice = createSlice({
    name: "user",
    initialState,
    // ユーザーのストアを変更する関数を定義
    reducers: {
        updateUser(
            state,
            action: PayloadAction<UpdateUser>,
        ) {
            return { ...state, ...action.payload };
        },
        reset() {
            return { ...initialState };
        },
    },
});
```

ここで、定義したユーザー情報を更新してみましょう。

```/pages/index.tsx
import { useDispatch } from "react-redux";
import { AppDispatch } from "store";
import { userSlice } from "@/store/user"
 
const Home: React.FC = () => {
    const dispatch: AppDispatch = useDispatch();

    const updateUser = () => {
        dispatch(userSlice.actions.updateUser({ username: "React", email: "react@gmail.com" }))
    };
};

export default Home;
```

実際にローカルストレージを見れば、ストアの内容が変更されていることが確認できます。

# 注意事項

## Dispatchの型定義は必ず行え

storeの中で非同期処理を行う場合、デフォルトのdispatchでは非同期処理を行うことが出来ません。

なので、``/store/index.ts``の中で``AppDispatch``を定義し、dispatchを使用する場合は面倒くさいのですが、必ずAppDispatchの型を指定してください。

かなり説明を端折ったので、分からに事があればコメント欄にてご質問ください。

以上、「Next.jsでRedux-toolkitをコピペだけでセットアップ」でした！

Thank you for reading