Reactで状態管理をする方法についてまとめてみる
Reactの実務経験は無いので、誤りがあれば指摘いただければ幸いです!
状態管理の手法
- useState
- useReducer
useState
関数コンポーネントの中でローカルなstateを使うことができるフック
useStateは現在の state の値と、更新関数のペアを返します
Todos Component
const Todos = () => {
const [title, setTitle] = useState("")
const handleSubmit = (e) => {
e.preventDefault();
const data = {
id: new Date().getTime(),
title,
created_at: new Date()
};
setTodos((prevData) => [...prevData, data]);
setTitle("");
};
return (
<>
<h2>Todos</h2>
<form onSubmit={handleSubmit}>
<input
type="text"
onChange={(e) => setTitle(e.target.value)}
value={title}
/>
</form>
<ul>
{todos.map((todo) => (
<TodoItem todo={todo} key={todo.id} />
))}
</ul>
</>
);
};
export default Todos;
コンポーネント単位で管理しているため、親子関係になっていればpropsとしてstateを渡し、他のコンポーネントでデータを反映させることは可能。
親子関係がなく、それぞれが独立したコンポーネントの場合、後述する Redux useContext 等の props以外の情報共有手段が必要になる。
公式
https://ja.reactjs.org/docs/hooks-state.html
codesandbox
https://codesandbox.io/s/usestate-todo-app-2i51b?file=/src/components/TodoItem.jsx:105-113
useReducer
useStateでは、 現在のstateとstateを更新するための関数が返ってきていました。
useReducerは、第一引数に関数(reducer)、第二引数にstateの初期値を渡すと、現在のstateとdispatchメソッドとペアで返ってきます。
dispatchは、reducerに actionを dispatchし、reducerに伝えます。
actionを受け取ったreducerは、action.typeで分岐して処理する内容をきめている。
ざっくり書くと、
一つ前の state と dispatch された actionを使って新しいstateを生成するための 「関数」 です。
公式サイトより↓
// state初期値
const initialState = {count: 0};
// action.type によって処理する内容を決める
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
onClick={() => dispatch({type: 'decrement'})} のように、 actionを dispatchすると
reducer 関数の中で、 action.type の分岐が実行される。
case 'decrement':
return {count: state.count - 1};
codesandboxで、簡単なフォームを作ってみました。
このサンプルでは、 use-immer を使用しています。
codesandbox
https://codesandbox.io/s/usereducer-form-mjnzj?file=/src/App.js
Flux In-Depth Overview
https://facebook.github.io/flux/docs/in-depth-overview#structure-and-data-flow
公式 useReducer
https://ja.reactjs.org/docs/hooks-reference.html#usereducer