ReactでTodoアプリを作っているのだが、stateで管理しているタスクを更新し、更新後のstateをセッションストレージに保存しようとすると、何故か更新前のstateが保存されている。
つまり、更新したはずのstateが反映されていないのだ。
この問題についての解決法を本記事ではまとめていく。
元のコード
stateはuseState
で管理し、以下のフォームからタスクを追加する。
const [tasks, setTasks] = useState([]);
// タスクの追加
const createTask = (e) => {
e.preventDefault();
const { taskName } = e.target.elements;
setTasks([{
name: taskName.value,
date: dateFormat(new Date()),
}, ...tasks]);
saveToSessionStorage(tasks);
}
8行目のsetTasks
で既存のタスクに新規タスクを追加し、13行目の関数呼び出しでセッションストレージにtasks
を保存している。
一見これでうまくいくように見えるが、実はuseState
で管理されるstateは、関数呼び出し後にしか更新されないのだ。
つまり、createTask
関数内では更新後のtasks
を参照することは出来ないということ。
一時変数に更新後のstateを保存する
この問題を解決するには、更新後のstateをいったん一時変数に保存させておく必要がある。
const [tasks, setTasks] = useState([]);
// タスクの追加
const createTask = (e) => {
e.preventDefault();
const { taskName } = e.target.elements;
// 更新後のstateを一時的に保存
const tmpTasks = [{
name: taskName.value,
date: dateFormat(new Date()),
}, ...tasks];
setTasks(tmpTasks);
saveToSessionStorage(tmpTasks);
}
元コードを修正したものがこちら。
9行目、tmpTasks
に更新後のstateを一時的に保存し、これをsetTasks
、saveToSessionStorage
でそれぞれ利用している。
一手間必要になるが、これで更新後のstateを扱うことができるようになる。