はじめに
ReactでDBを使用せずにデータの永続化を実現する方法を調べてまとめました。
LocalStrageを使用したデータ永続化
今回は、JavaScriptでブラウザにデータを記録するweb APIであるlocalStrageを使用して実現します。
localStrageでは、主要なブラウザであれば5MBまでデータを永続的に保存できますが、
「クロスサイトスクリプティング(XSS)攻撃に対する脆弱性」などのセキュリティ上のリスクもあるため、個人情報などの機密情報の取り扱いには注意が必要です。
実装方法
Todoアプリでのデータ永続化の実装例を挙げます。
下記コードは、LocalStrageでのデータ永続化を実装したTodoアプリのカスタムフックuseTodo.jsです。
import { useState, useEffect } from "react";
// LocalStrageに保存されたtodoが0件の場合に表示する初期todo
const DEFAULT_TODO = [
{ id: 1, todoTitle: "ジムに行く" },
{ id: 2, todoTitle: "植物の水やり" },
{ id: 3, todoTitle: "部屋の掃除" },
];
// LocalStrageのtodo取得
// 取得件数が0件の場合はDEFAULT_TODOを表示対象とする
const STORED_TODO = localStorage.getItem("todo");
const INITIAL_TODO = STORED_TODO
? JSON.parse(STORED_TODO).length === 0
? DEFAULT_TODO
: JSON.parse(STORED_TODO)
: DEFAULT_TODO;
export const useTodo = () => {
// INITIAL_TODOを最初に表示する
const [todo, setTodo] = useState(() => 67INITIAL_TODO);
const [inputValue, setInputValue] = useState("");
const [idCounter, setIdCounter] = useState(todo.length + 1);
useEffect(() => {
// todoステートが更新されるたびにその内容をLocalStrageに保存する
localStorage.setItem("todo", JSON.stringify(todo));
}, [todo]);
// todoの追加処理
const addTodo = () => {
setIdCounter(idCounter + 1);
const newTodo = {
id: idCounter,
todoTitle: inputValue,
};
setTodo([...todo, newTodo]);
setInputValue("");
};
// todoの削除処理
const deleteTodo = (id) => {
const newTodoList = [...todo].filter((item) => item.id !== id);
setTodo(newTodoList);
};
return [todo, inputValue, setInputValue, addTodo, deleteTodo];
};
LocalStrageを使用している箇所に絞って説明します。
まずtodoステートの初期値にセットしている定数INITIAL_TODOには、最初にLocalStrageから取得した値をセットしています。
// LocalStrageのtodo取得
// 取得件数が0件の場合はDEFAULT_TODOを表示対象とする
const STORED_TODO = localStorage.getItem("todo");
const INITIAL_TODO = STORED_TODO
? JSON.parse(STORED_TODO).length === 0
? DEFAULT_TODO
: JSON.parse(STORED_TODO)
: DEFAULT_TODO;
この時、LocalStrageにtodoというキーが存在しない場合、またはLocalStrageから取得したtodoに何も入っていない(todo配列の要素数が0)の場合は、下記DEFAULT_TODOをINITIAL_TODOにセットするようにしています。
// LocalStrageに保存されたtodoが0件の場合に表示する初期todo
const DEFAULT_TODO = [
{ id: 1, todoTitle: "ジムに行く" },
{ id: 2, todoTitle: "植物の水やり" },
{ id: 3, todoTitle: "部屋の掃除" },
];
useEffectを使用して、todoステートの値が変わるたび(todoが追加/削除されるたび)にLocalStrageに最新のtodoをLocalStrageに保存しています。
useEffect(() => {
// todoステートが更新されるたびにその内容をLocalStrageに保存する
localStorage.setItem("todo", JSON.stringify(todo));
}, [todo]);
これで、画面を再読み込みしても、追加したtodoが消えずに表示されるようになりました!
参考サイト
mdn web docs: Window.localStorage
Local Storageを使ってみる
useState と localStorage で永続化する方法
localStorageがセキュリティ面で使わない方がよいと言われる理由