神戸学院大学 経営学部 林坂ゼミ

React 入門トップページ

« 戻る 次へ »

React 入門

TypeScript コメント掲示板アプリの開発

WebStorage の利用

ここまでの作業でコメントの一覧表示,新規投稿,削除の作業をページの遷移を伴うことなく(つまり同じ URL で)できるようになりました.しかし,ブラウザで再読み込みボタンをクリックすると初期状態に戻ってしまいます.ここでは WebStorage を使ってブラウザ内にコメント情報を保存する方法を示します.これによって,ブラウザを閉じたり,再読み込みをしてもデータが保持されるようになります.なお,WebStorage の詳細は MDN を参照してください.

まず,ブラウザで WebStorage の内容を確認する方法について説明します.Google Chrome では DevTools で「Application」の「Storage」にある「Local storage」と「Session storage」を参照することでブラウザに保存された情報を確認したり,編集,削除ができます.

ts-2024-30

useState で管理しているコメントの情報を WebStorage に保存することを考えます.今回はコメントの追加処理と削除処理を行うタイミングで WebStorage に保存するとよいでしょう.したがって,CommentListPage.tsx の追加と削除の処理に WebStorage にも保存するコードを追加します.WebStorage には「キー」と「値(文字列)」のペアで保存します.このとき,newResults はオブジェクト形式であるので,文字列形式に変換するために JSON.stringify() 関数を利用しています.

src/components/CommentListPage.tsximport React from 'react'
import { useState } from 'react';
import Comment from './Comment';
import CreateForm from './CreateForm';

interface CommentData {
  id: number;
  title: string;
  body: string;
  updated_at: string;
}

interface Results {
  count: number;
  next: string | null;
  previous: string | null;
  results: CommentData[];
}

const CommentListPage: React.FC = () => {

  const [results, setResults] = useState<Results>({
    "count":10,
    "next":"http://127.0.0.1:8000/comments/?page=2",
    "previous":null,
    "results":[
      {
        "id":9,
        "title":"9個目のコメント",
        "body":"コメントの本文9",
        "updated_at":"2023-11-21T11:20:00"
      },
      {
        "id":10,
        "title":"10個目のコメント",
        "body":"コメントの本文10",
        "updated_at":"2023-11-21T11:10:00"
      }
    ]
  });

  const handleDeleteButtonClick = (commentId: number) => {
    if (!window.confirm("削除しますか?")) {
      return;
    }
    const newComments = [...results.results].filter((comment) => {
      return comment.id !== commentId;
    });
    const newResults: Results = {
      "count": results.count - 1, // コメント数は1減らす
      "previous": results.previous,
      "next" : results.next,
      "results": newComments
    };
    setResults(newResults);
    // WebStorageに保存
    localStorage.setItem('results', JSON.stringify(newResults));
  };

  const commentItems = results.results.map((comment) => {
    return (
      <Comment
        key={comment.id}
        comment={comment}
        onDelete={handleDeleteButtonClick}
      />
    )
  });

  const handelCreateFormSubmit = (title: string, body: string) => {
    const newComments = [...results.results];  // スプレッド構文でコメントの配列だけを取り出す
    newComments.unshift({   // unshift で先頭に追加,push では最後に追加
      id: Date.now(),
      title: title,
      body: body,
      updated_at: "2024-03-18T12:00:00",
    });
    const newResults = {
      "count": results.count + 1, // コメント数は1増やす
      "previous": results.previous,
      "next" : results.next,
      "results": newComments,   // これがコメントの配列
    };
    setResults(newResults); // 画面を更新
    // WebStorageに保存
    localStorage.setItem('results', JSON.stringify(newResults));
  }

  return (
    <div className="container">
      <h1>コメント一覧</h1>
      {commentItems}

      <CreateForm
        onSubmit={handelCreateFormSubmit}
      />
    </div>
  )
}

export default CommentListPage

ブラウザでコメントを投稿した後に WebStorage の内容を確認します.「results」をキーとしてコメントの情報が JSON 形式の文字列として格納されていることがわかります.

ts-2024-31

コメントの追加と削除時に WebStorage へ保存されることを確認しました.現時点ではブラウザを再読み込みしたときには初期状態に戻ってしまいます.最後にブラウザを再読込したり,再起動したときに WebStorage へ保存されたコメント情報が表示されるようにします.このためには ページが再読込されたときだけ WebStorage からデータを読み出したいので,useEffect を使います.まず,プログラムの先頭で useEffect をインポートします.

src/components/CommentListPage.tsx(抜粋)import { useState, useEffect } from 'react';

ページの再読込時だけ処理を実行したいので,useEffect の第2引数には空配列 [] を渡します.

src/components/CommentListPage.tsx(抜粋)useEffect(() => {実行したい処理}, []);

実行したい処理,つまり WebStorage からの読み込みとデータの更新作業を上の { ... } の中に入力します.このとき,WebStorage に「results」キーが存在しない場合の処理も記載していることに注意してください.キーが存在した場合には文字列形式のデータを JSON.parse() によってオブジェクト形式に変換しています.

src/components/CommentListPage.tsx(抜粋)useEffect(() => {
  let localResults: Results;
  const localStorageResults = localStorage.getItem('results');

  if (localStorageResults === null) {
    localResults = results;    // 存在しない場合には初期値を設定
  } else {
    localResults = JSON.parse(localStorageResults);
  }
  setResults(localResults);
}, []);

ページの再読込時に WebStorage の内容が表示されることを確認してください.なお,WebStorage の LocalStorage はブラウザごとに保存され,有効期限はありません.ブラウザや OS を再起動しても同じブラウザであれば保存された内容が毎回読み出されます.SessionStorage では1セッションのデータのみを保存するので,ブラウザを再起動した場合や,新たなタブを開いた場合にはその情報が利用されません.

ts-2024-32

ローカルで完結するシステムであればこの段階でほぼ完成です.次のページではバックエンドの API サーバに接続して API からコメントの一覧を取得したり,投稿したりするフロントエンドを React で作成します.次のページに進んで作業を継続する場合はこのページで追加した WebStorage に関する部分を削除するかコメントアウトするかして,前のページの状態に戻しておいてください.

目次に戻る