今回やること
前回は、Reactを動かしてJSXを表示しました。
今回は、一覧・新規登録・編集の3画面を用意して、ボタンで表示を切り替えられるようにします。
公開日:更新日:
前回は、Reactを動かしてJSXを表示しました。
今回は、一覧・新規登録・編集の3画面を用意して、ボタンで表示を切り替えられるようにします。
この段階では、各画面の中身はまだ作りません。
画面名を表示し、切り替わったことだけ確認します。
今回から実際のアプリ画面を作っていくため、画面全体を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です。
現在はボタンを置いただけなので、クリックしても表示は変わりません。
ボタンをクリックしたときに画面を切り替えるには、 「現在どの画面を表示しているか」をReactに覚えておいてもらう必要があります。
まずは、一覧画面と新規登録画面の2画面を切り替えてみましょう。
画面を切り替えるために、今回はReactのuseStateを使います。
詳しい仕組みは、実際に動かしたあとで整理します。
App.jsxの先頭でuseStateを読み込み、
Appの中でscreenとsetScreenを用意します。
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>
);
}
ファイルを保存して、ブラウザを確認してみましょう。
「新規登録」をクリックすると新規登録画面へ切り替わり、
「一覧へ」をクリックすると一覧画面へ戻ればOKです。
まだ「編集」ボタンをクリックしても何も起こりません。
その前に、今使ったStateやuseStateがどのような仕組みなのか整理しておきましょう。
Reactでは、画面の表示に使う
変化する値を管理する仕組みをState(ステート)
と呼びます。
今回は、現在どの画面を表示しているかをStateとして管理しています。
Stateを用意するときに使うのが、ReactのuseStateです。
今回は、次の1行で画面を管理するStateを用意しています。
const [screen, setScreen] = useState("list");
今回は、現在表示している画面を管理するStateをscreen Stateと呼ぶことにします。
screenは現在の値を保持するstate変数、
setScreenはStateを更新するための更新関数です。
| 部分 | 役割 |
|---|---|
useState("list") |
初期値を"list"としてStateを用意する |
screen |
現在の値を保持するstate変数 |
setScreen |
Stateを更新するための更新関数 |
"list" |
Stateの初期値 |
更新関数には、setScreenのように
「set + state変数名」という名前を付けるのが一般的です。
アプリを最初に表示したときは、screenの値が"list"になります。
screen
↓
"list"
今回は、次の3つの文字列を使って画面を表します。
| 値 | 表す画面 |
|---|---|
"list" |
一覧画面 |
"create" |
新規登録画面 |
"edit" |
編集画面 |
Stateの値を変更するときは、更新関数setScreenを使います。
先ほど「新規登録」ボタンで実行していたのは、次の処理です。
setScreen("create");
これを実行すると、state変数screenの値が
"create"へ変わります。
screen
"list"
↓
setScreen("create")
↓
"create"
一覧画面の「新規登録」ボタンでは、
onClick={() => setScreen("create")}を指定しています。
ボタンをクリックするとscreenが"create"になり、
次の条件に当てはまります。
if (screen === "create")
その結果、新規登録画面のJSXが表示されます。
「一覧へ」をクリックするとsetScreen("list")が実行され、
一覧画面へ戻ります。
一覧画面と新規登録画面の切り替えで仕組みが分かったので、 同じ方法で編集画面も追加してみましょう。
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画面を行き来できれば、Stateを使った画面切り替えは完成です。
なぜsetScreenでStateを変更すると、ブラウザの表示まで変わるのでしょうか。
更新関数setScreenでStateを更新すると、
Appコンポーネントが再レンダリングされます。
setScreen(...)
↓
Stateが更新される
↓
Appコンポーネントが再レンダリングされる
↓
Appの関数がもう一度実行される
↓
新しいscreenの値で表示するJSXが決まる
↓
必要な変更が画面へ反映される
再レンダリングされると、Appの関数がもう一度実行され、
新しいStateの値を使って表示するJSXが決まります。
普通の変数の値を変更しても、それ自体をきっかけにReactが再レンダリングするわけではありません。
今回登場したものを整理すると、次のようになります。
| 種類 | 今回登場したもの |
|---|---|
| React | State、useState、state変数、更新関数、Stateの更新による再レンダリング |
| JavaScript | ifによる条件分岐、分割代入 |
ReactではJavaScriptの機能を使いながら、 StateのようなReactの仕組みを組み合わせて画面を作っていきます。
useStateを使ってStateを用意できるscreenは現在の値を保持するstate変数setScreenはStateを更新する更新関数set + state変数名」とする名前が一般的
今回のApp.jsxの完成コードです。
state変数screenの値で一覧・新規登録・編集を切り替えます。
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>
);
}