この記事はTOWN株式会社アドベントカレンダー6日目の記事です(大遅刻して申し訳ないです。。。)
https://adventar.org/calendars/4335
React HooksとはReact16.8から追加された機能で、関数コンポーネントにstateなどの機能を使えるようになった記法です。
https://ja.reactjs.org/docs/hooks-intro.html
Redux toolkitとはどうしても複雑な記述を書かなくてはいけないイメージが(個人的に)あるreduxを簡潔に書くことができるライブラリです。reduxの公式チームがリリースしているそうです。
https://github.com/reduxjs/redux-toolkit
今回はreact hooksとredux toolkitを使ってtodoアプリを作成してみました。
#アプリの作成
まずcreate-react-app
を使ってアプリのテンプレートを作成します。
npx create-react-app hooks-toolkit-sample
パッケージをインストールします。
yarn add react-redux @reduxjs/toolkit
or
npm i react-redux @reduxjs/toolkit
yarn start
もしくはnpm start
でアプリを起動します。reactのロゴsvgなどのいらないファイルやいらない記述等は削除しておきます。
#actionとreducerの作成
redux toolkitのcreateSliceを使用し、actionとreducerを同時に作成しています。このおかげでactionとreducerを別々のディレクトリに分ける必要がなくなりました。
import { createSlice } from "@reduxjs/toolkit";
const listModule = createSlice({
name: "list",
initialState: [],
reducers: {
addList: (state, action) => [...state, action.payload],
deleteList: (state, action) => state.filter(el => el.id !== action.payload),
}
});
export default listModule;
#storeの作成
reducerとmiddlewareを登録します。先ほどのmoduleのreducerをredux toolkitのcombineReducers
を使って登録しています。
import { combineReducers, configureStore } from "@reduxjs/toolkit";
import listModule from "./modules/listModule";
const rootReducer = combineReducers({
list: listModule.reducer,
});
export const setupStore = () => {
const store = configureStore({
reducer: rootReducer,
});
return store
}
#コンポーネントの作成
まずuseDispatch()
を使ってactionが使えるようにします。
todoを追加するためのテキストのinputの操作ですが、inputのonChange
にhandleChangeList
関数を設定して文字を入力するたびに関数が実行されるようにします。
そしてreact hooksのuseState
を用い、入力したテキストを一時的にnewListName
のstateに入れておきます。
addList
ボタンを押した瞬間にnewListName
を引数にしてactionのaddList
を実行し、storeのstateにtodoのテキストが入ることで画面が更新されます。
import React from 'react';
import { useState } from 'react';
import { useDispatch, useSelector } from "react-redux";
import listModule from "../modules/listModule";
import List from "./List.js";
const App = () => {
const lists = useSelector(state => state.list);
const [newListName, setListName] = useState("");
const dispatch = useDispatch();
const addList = () => {
if (newListName !== "") {
dispatch(listModule.actions.addList({id: lists.length > 0 ? lists.reduce((a,b) => a.id > b.id ? a : b).id + 1 : 1, title: newListName}));
}
setListName("");
};
const handleChangeList = (e) => {
setListName(e.target.value);
};
return (
<div className="App">
<p>Redux TODO sample</p>
{lists.map((list) =>
<List key={list.id} item={list} />
)}
<input type="text" onChange={handleChangeList} value={newListName}/>
<button onClick={addList}>addList</button>
</div>
);
};
export default App;
import React from 'react';
import { useState } from 'react';
import { useDispatch, useSelector } from "react-redux";
import listModule from "../modules/listModule";
const List = (props) => {
const { item } = props;
const dispatch = useDispatch();
const deleteList = () => dispatch(listModule.actions.deleteList(item.id));
return (
<div>
{item.title}
<button onClick={deleteList}>deleteList</button>
</div>
)
}
export default List;
ここまでクラスコンポーネントを使わず、かつとてもコンパクトにreduxのアプリを作成することが出来ました。書いていてかなり楽しかったので今度はもう少し複雑なアプリも作ってみようかと思います。
参考:
TypescriptとReact HooksでReduxはもうしんどくない
https://qiita.com/ky7ieee/items/b3f43ecc497b9115449a
Redux Hooks によるラクラク dispatch & states
https://qiita.com/Ouvill/items/569384e5c8c7ce78f98e
Redux の記述量多すぎなので、 Redux の公式ツールでとことん楽をする。 ( Redux Toolkit)
https://qiita.com/Ouvill/items/a76e9cbce569d01f2931