Stateで画面を切り替えよう

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

今回やること

前回は、Reactを動かしてJSXを表示しました。

今回は、アプリに一覧・新規登録・編集の3画面がある状態を作り、 screen Stateで表示を切り替えます。

スポンサーリンク

まずは画面の名前を表示する

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

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

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

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

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に覚えておいてもらう 必要があります。

Stateとは?

Reactでは、画面の表示に使う 変化する値を管理する仕組みをState(ステート) と呼びます。

今回のアプリでは、「一覧画面」「新規登録画面」「編集画面」の どの画面を表示しているかによって、ブラウザに表示する内容が変わります。

そこで、現在表示している画面を表す値をStateとして管理します。

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

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

たとえば、現在の値が"list"なら一覧画面を表示し、 "create"なら新規登録画面を表示する、という使い方をします。

useStateでStateを用意する

Stateを用意するには、ReactのuseStateを使います。

まず、App.jsxの先頭でuseStateを読み込みます。

import { useState } from "react";

次に、Appの中で次のように書きます。

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

  // このあと画面の表示を切り替えます
}

今回のポイントは、次の1行です。

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

今回は、現在表示している画面を管理するStateを screen Stateと呼ぶことにします。

このうち、screenは現在の値を保持する state変数setScreenはStateを更新するための 更新関数です。

更新関数には、setScreenのように 「set + state変数名」という名前を付けるのが一般的です。

それぞれの部分を分けて見てみましょう。

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

アプリを最初に表示したときは、 screenの値が"list"になります。

screen
↓
"list"

setScreenでStateを変更する

Stateの値を変更するときは、 先ほど用意した更新関数setScreenを使います。

たとえば、次のように書きます。

setScreen("create");

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

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

同じように、setScreen("edit")とすれば編集画面を表す値に、 setScreen("list")とすれば一覧画面を表す値に変更できます。

このstate変数screenの値を使って、 次に表示する画面を切り替えてみましょう。

Stateの値で表示を切り替える

if文でstate変数screenの値を条件にして、 表示する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>
  );
}

今回は、state変数screenの値が"create"なら新規登録画面、 "edit"なら編集画面を表示します。

どちらにも当てはまらない場合は、最後のreturnで一覧画面を表示します。 一覧画面を基本の画面として扱うため、最後のreturnにしています。

一覧画面の「新規登録」ボタンをクリックすると、次の部分が実行されます。

onClick={() => setScreen("create")}

setScreen("create")によって state変数screenの値が"create"になるため、 次の条件に当てはまるようになります。

if (screen === "create")

その結果、新規登録画面のJSXが表示されます。

同じように「編集」をクリックするとstate変数screenの値が "edit"になり、編集画面が表示されます。

新規登録画面や編集画面の「一覧へ」では、 setScreen("list")を実行して一覧画面へ戻しています。

保存してブラウザを確認し、 「新規登録」「編集」で画面が変わり、「一覧へ」で戻ればOKです。

Stateが変わると再レンダリングされる

なぜsetScreenでStateを変更すると、 ブラウザの表示まで変わるのでしょうか。

更新関数setScreenでStateを更新すると、 Appコンポーネントが再レンダリングされます。

そのとき、Appの関数がもう一度実行され、 新しいStateの値を使って表示するJSXが決まります。

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

このように、Stateが更新されるとReactはコンポーネントを再レンダリングし、 新しいStateの値に合わせて画面を更新します。

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

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で保存して完成
スポンサーリンク