Stateで画面を切り替えよう

← 第2
Reactアプリ作成(JS編)3 / 15
4回 →

今回やること

前回は、Reactを動かしてJSXを表示しました。
今回は、一覧・新規登録・編集の3画面を用意して、ボタンで表示を切り替えられるようにします。

一覧・新規登録・編集の3画面を切り替えられるReactアプリ
今回の完成イメージ:3画面を切り替えるアプリ
スポンサーリンク

1. まずは画面の名前を表示してみよう

この段階では、各画面の中身はまだ作りません。
画面名を表示し、切り替わったことだけ確認します。

今回から実際のアプリ画面を作っていくため、画面全体をmainで囲みます。
また、アプリのタイトルやボタンを置く部分はheaderで囲んでおきます。

第2回で用意したCSSを画面に適用するため、JSXにclassNameを追加します。
JSXでは、HTMLのclassの代わりにclassNameでCSSクラスを指定します。
複数の操作ボタンは、header-actionsというdivにまとめます。

App.jsxを、次のように書き換えてみましょう。

export default function App() {
  return (
    <main className="list-screen">
      <header className="list-header">
        <h1>気になるものリスト</h1>
        <div className="header-actions">
          <button type="button">新規登録</button>
          <button type="button">編集</button>
        </div>
      </header>

      <h2 className="screen-title">一覧画面</h2>
    </main>
  );
}

ブラウザで画面を確認しよう

次のような画面になればOKです。
現在はボタンを置いただけなので、クリックしても表示は変わりません。

気になるものリストのタイトル、新規登録ボタン、編集ボタン、一覧画面の見出しが表示された画面
タイトルと2つのボタン、一覧画面の名前が表示されています。

ボタンをクリックしたときに画面を切り替えるには、 「現在どの画面を表示しているか」をReactに覚えておいてもらう必要があります。

2. 一覧画面と新規登録画面を切り替えてみよう

まずは、一覧画面と新規登録画面の2画面を切り替えてみましょう。
画面を切り替えるために、今回はReactのuseStateを使います。 詳しい仕組みは、実際に動かしたあとで整理します。

App.jsxの先頭でuseStateを読み込み、 Appの中でscreensetScreenを用意します。

import { useState } from "react";

export default function App() {
  const [screen, setScreen] = useState("list");

  if (screen === "create") {
    return (
      <main className="form-screen">
        <header className="screen-header">
          <h1>気になるものリスト</h1>
          <div className="header-actions">
            <button type="button" className="secondary" onClick={() => setScreen("list")}>
              一覧へ
            </button>
          </div>
        </header>

        <h2 className="screen-title">新規登録画面</h2>
      </main>
    );
  }

  return (
    <main className="list-screen">
      <header className="list-header">
        <h1>気になるものリスト</h1>
        <div className="header-actions">
          <button type="button" onClick={() => setScreen("create")}>
            新規登録
          </button>
          <button type="button">編集</button>
        </div>
      </header>

      <h2 className="screen-title">一覧画面</h2>
    </main>
  );
}

ブラウザで2画面の切り替えを確認しよう

ファイルを保存して、ブラウザを確認してみましょう。
「新規登録」をクリックすると新規登録画面へ切り替わり、 「一覧へ」をクリックすると一覧画面へ戻ればOKです。

一覧・新規登録の2画面を切り替えられるReactアプリ
一覧画面と新規登録画面を切り替える

まだ「編集」ボタンをクリックしても何も起こりません。
その前に、今使ったStateやuseStateがどのような仕組みなのか整理しておきましょう。

StateとuseStateとは?

Reactでは、画面の表示に使う 変化する値を管理する仕組みをState(ステート) と呼びます。
今回は、現在どの画面を表示しているかをStateとして管理しています。

Stateを用意するときに使うのが、ReactのuseStateです。
今回は、次の1行で画面を管理するStateを用意しています。

const [screen, setScreen] = useState("list");

今回は、現在表示している画面を管理するStateをscreen Stateと呼ぶことにします。
screenは現在の値を保持するstate変数setScreenはStateを更新するための更新関数です。

useStateで登場する値と関数
部分 役割
useState("list") 初期値を"list"としてStateを用意する
screen 現在の値を保持するstate変数
setScreen Stateを更新するための更新関数
"list" Stateの初期値

更新関数には、setScreenのように 「set + state変数名」という名前を付けるのが一般的です。
アプリを最初に表示したときは、screenの値が"list"になります。

screen
↓
"list"

今回は、次の3つの文字列を使って画面を表します。

画面を表すStateの値
表す画面
"list" 一覧画面
"create" 新規登録画面
"edit" 編集画面

setScreenでStateを変更する

Stateの値を変更するときは、更新関数setScreenを使います。
先ほど「新規登録」ボタンで実行していたのは、次の処理です。

setScreen("create");

これを実行すると、state変数screenの値が "create"へ変わります。

screen
"list"
  ↓
setScreen("create")
  ↓
"create"

一覧画面の「新規登録」ボタンでは、 onClick={() => setScreen("create")}を指定しています。
ボタンをクリックするとscreen"create"になり、 次の条件に当てはまります。

if (screen === "create")

その結果、新規登録画面のJSXが表示されます。
「一覧へ」をクリックするとsetScreen("list")が実行され、 一覧画面へ戻ります。

3. 編集画面への切り替えも追加しよう

一覧画面と新規登録画面の切り替えで仕組みが分かったので、 同じ方法で編集画面も追加してみましょう。

screen === "create"の条件分岐のあとに、 screenの値が"edit"のときに表示するJSXを追加します。

if (screen === "edit") {
  return (
    <main className="form-screen">
      <header className="screen-header">
        <h1>気になるものリスト</h1>
        <div className="header-actions">
          <button type="button" className="secondary" onClick={() => setScreen("list")}>
            一覧へ
          </button>
        </div>
      </header>

      <h2 className="screen-title edit-title">編集画面</h2>
    </main>
  );
}

次に、一覧画面の「編集」ボタンにもonClickを追加します。

<button type="button" onClick={() => setScreen("edit")}>
  編集
</button>

これで「編集」をクリックするとscreenの値が"edit"になり、 編集画面のJSXが表示されます。
新規登録画面と編集画面のどちらも、「一覧へ」ではsetScreen("list")を実行して一覧画面へ戻します。

また、screenの値が"create"でも"edit"でもない場合は、 最後のreturnで一覧画面を表示します。
一覧画面を基本の画面として扱うため、最後のreturnにしています。

ブラウザで3画面の切り替えを確認しよう

保存してブラウザを確認し、次の操作を試してみましょう。

  • 「新規登録」をクリックすると、新規登録画面へ切り替わる
  • 新規登録画面の「一覧へ」をクリックすると、一覧画面へ戻る
  • 「編集」をクリックすると、編集画面へ切り替わる
  • 編集画面の「一覧へ」をクリックすると、一覧画面へ戻る

3画面を行き来できれば、Stateを使った画面切り替えは完成です。

一覧・新規登録・編集画面を切り替える
一覧・新規登録・編集画面を切り替える

Stateが変わるとどうなる?

なぜsetScreenでStateを変更すると、ブラウザの表示まで変わるのでしょうか。
更新関数setScreenでStateを更新すると、 Appコンポーネントが再レンダリングされます。

setScreen(...)
  ↓
Stateが更新される
  ↓
Appコンポーネントが再レンダリングされる
  ↓
Appの関数がもう一度実行される
  ↓
新しいscreenの値で表示するJSXが決まる
  ↓
必要な変更が画面へ反映される

再レンダリングされると、Appの関数がもう一度実行され、 新しいStateの値を使って表示するJSXが決まります。
普通の変数の値を変更しても、それ自体をきっかけにReactが再レンダリングするわけではありません。

ReactとJavaScriptを分けて見てみよう

今回登場したものを整理すると、次のようになります。

今回登場したReactとJavaScriptの要素
種類 今回登場したもの
React State、useState、state変数、更新関数、Stateの更新による再レンダリング
JavaScript ifによる条件分岐、分割代入

ReactではJavaScriptの機能を使いながら、 StateのようなReactの仕組みを組み合わせて画面を作っていきます。

今回のまとめ

  • StateはReactで変化する値を管理する仕組み
  • useStateを使ってStateを用意できる
  • screenは現在の値を保持するstate変数
  • setScreenはStateを更新する更新関数
  • 更新関数は「set + state変数名」とする名前が一般的
  • Stateの値に応じて表示するJSXを切り替えた
  • Stateが更新されるとコンポーネントが再レンダリングされる

今回の完成コード

今回のApp.jsxの完成コードです。
state変数screenの値で一覧・新規登録・編集を切り替えます。

src/App.jsx

import { useState } from "react";

export default function App() {
  const [screen, setScreen] = useState("list");

  if (screen === "create") {
    return (
      <main className="form-screen">
        <header className="screen-header">
          <h1>気になるものリスト</h1>
          <div className="header-actions">
            <button type="button" className="secondary" onClick={() => setScreen("list")}>
              一覧へ
            </button>
          </div>
        </header>

        <h2 className="screen-title">新規登録画面</h2>
      </main>
    );
  }

  if (screen === "edit") {
    return (
      <main className="form-screen">
        <header className="screen-header">
          <h1>気になるものリスト</h1>
          <div className="header-actions">
            <button type="button" className="secondary" onClick={() => setScreen("list")}>
              一覧へ
            </button>
          </div>
        </header>

        <h2 className="screen-title edit-title">編集画面</h2>
      </main>
    );
  }

  return (
    <main className="list-screen">
      <header className="list-header">
        <h1>気になるものリスト</h1>
        <div className="header-actions">
          <button type="button" onClick={() => setScreen("create")}>
            新規登録
          </button>
          <button type="button" onClick={() => setScreen("edit")}>
            編集
          </button>
        </div>
      </header>

      <h2 className="screen-title">一覧画面</h2>
    </main>
  );
}

アプリの完成状況

  • ✅ Reactを動かし、JSXを表示する
  • ✅ Stateで画面を切り替える
  • ⬜ 1件のデータを表示する
  • ⬜ 複数のデータを一覧表示する
  • ⬜ コンポーネントとpropsを使う
  • ⬜ コンポーネントを別ファイルへ分ける
  • ⬜ 新規登録画面を作る
  • ⬜ 一覧データをStateで管理する
  • ⬜ 編集画面を作る
  • ⬜ データを更新する
  • ⬜ データを削除する
  • ⬜ カテゴリ・ステータスで絞り込む
  • ⬜ キーワードで検索する
  • ⬜ localStorageで保存して完成
スポンサーリンク