Reactで状態・フォーム・リストを扱うの導入スライド
Reactで状態・フォーム・リストを扱う - なぜstateが必要か
増えているのに画面は0
コンソールの likes は押すたびに増えていますが、画面のいいねはずっと0のままです。
変数はちゃんと増えています。それなのに画面は動きません。なぜでしょうか。
let likes = 0;
function handleClick() {
likes = likes + 1;
}1 / 5
画面が変わらない理由
理由は2つあります。どちらもふつうの変数の性質です。
likes = likes + 1 と代入する
変数は増えるが、Reactへ合図が届かない
運よく App 関数が呼び直されても
let likes = 0 からやり直され、また0に戻る
画面に出したい値は、かならず state にします。
2 / 5
Reactで状態・フォーム・リストを扱う - なぜstateが必要か
壊れている場所を触る
クリック回数を増やし、useState に書き換えるを入れて見比べてください。
- 書き換えないままだと、回数を増やしても画面の数字は0のまま
- useState に書き換えると、同じ回数で画面の数字まで動く
- 変数の中身はどちらも同じように増えていて、変わるのは画面へ伝わる仕組みだけ
3 / 5
直すのは1行だけ
見た目はほぼ同じ2つのコードで、動くかどうかが分かれます。
書き換えるだけ(動かない)
let likes = 0;
function handleClick() {
likes = likes + 1;
}useStateを使う(動く)
const [likes, setLikes] = useState(0);
function handleClick() {
setLikes(likes + 1);
}書き方の中身は次のレッスンで説明します。
4 / 5
考えてみよう外しても進めます
コンソールには likes が正しく増えて出ているのに、画面のいいね表示は変わりません。原因はどれですか。
選ぶと、この枚の中で答えと理由を確かめられます。
5 / 5
Reactで状態・フォーム・リストを扱う - useState
1行で3つのことをする
const の1行が、初期値・いまの値・更新関数を同時に扱っています。
受け取る2つは、useState が返す配列の中身です。
| 書いてあること | やっていること |
|---|---|
| useState(0) | 最初の値を0にする |
| 左の likes | いまの値を受け取る |
| 左の setLikes | 更新する関数を受け取る |
1 / 5
Reactで状態・フォーム・リストを扱う - useState
配列の中身を見る
片側ずつ選び、初期値も動かして返ってくる中身を見てください。
- useState が返すのは、いまの値と更新する関数が入った配列
- 左が0番目でいまの値、右が1番目で更新する関数
- 名前は自由だが、更新関数は set と値の名前でそろえる
2 / 5
3つのつまずきどころ
この形はよく間違えます。あらかじめ見ておきます。
import を書き忘れる
useState is not defined のエラーで画面が真っ白になる
if の中や for の中で useState を呼ぶ
呼ばれる順番が回によって変わり、値が入れかわる
useState() と初期値を省略する
最初の値が undefined になり、画面に何も出ない
数値なら useState(0)、文字列なら useState("") のように、型に合った初期値を渡します。
3 / 5
更新関数の名前
名前は自由ですが、慣習からそろえておくと読みやすくなります。
そろえない書き方
const [likes, update] = useState(0);
const [open, change] = useState(false);setと値の名前でそろえる
const [likes, setLikes] = useState(0);
const [open, setOpen] = useState(false);読む人が名前を見ただけで、更新関数だと分かるようにします。
4 / 5
考えてみよう外しても進めます
useState() のように初期値を書かずに呼ぶと、最初の値はどうなりますか。
選ぶと、この枚の中で答えと理由を確かめられます。
5 / 5
Reactで状態・フォーム・リストを扱う - ボタンで更新
押してから変わるまで
1手ずつ進めて、setCount を呼んだあと画面がいつ変わるか確かめてください。
- 1手目は setCount を呼んだだけで、画面はまだ前のまま
- 2手目で React が画面を作り直す
- 同じ値を渡すと、React は作り直さない
1 / 5
関数を呼ぶか、渡すか
onClick にはかっこを付けず、関数そのものを渡します。
呼び出した結果を渡す
<button onClick={handleLike()}>いいね</button>関数そのものを渡す
<button onClick={handleLike}>いいね</button>かっこを付けると描画のたびにその場で実行され、押していないのに setLikes が呼ばれ続けます。
2 / 5
前の値から確実に積む
同じ回の中で likes は書きかわらないので、2回続けて呼ぶと結果がずれます。
いまの likes を読む
function handleDouble() {
setLikes(likes + 1);
setLikes(likes + 1);
}前の値を関数で受け取る
function handleDouble() {
setLikes((prev) => prev + 1);
setLikes((prev) => prev + 1);
}likes が0のとき、左は2行とも 0 + 1 を計算するので結果は1のままです。
3 / 5
Reactで状態・フォーム・リストを扱う - ボタンで更新
描画の間、値は変わらない
setLikes を呼んだ直後に console.log を書いても、画面と同じで古い値のままです。
新しい値は次の描画で作られる likes に入ります。同じ回の中では変わりません。
function handleLike() {
setLikes(likes + 1);
console.log(likes); // まだ古い値
}4 / 5
考えてみよう外しても進めます
likes が0のとき、setLikes(likes + 1) を2回続けて呼ぶと、いいねはいくつになりますか。
選ぶと、この枚の中で答えと理由を確かめられます。
5 / 5
Reactで状態・フォーム・リストを扱う - 複数のstate
stateはいくつでも作れる
画面が持つ状態は1つとはかぎりません。useState は必要なだけ並べて書けます。
3つとも独立していて、どれか1つを更新しても他は変わりません。
| state | 役割 |
|---|---|
| likes | いいね数 |
| activeTab | いま開いているタブ |
| displayName | 表示名 本名かローマ字か |
1 / 5
まとめるか、分けるか
タブだけ変えたいのに、まとめると毎回オブジェクトを作り直すことになります。
1つにまとめた場合
setUi({ ...ui, activeTab: "作品" });別々に分けた場合
setActiveTab("作品");関係のない値は別の state に分けるほうが、書くのも読むのも簡単です。
2 / 5
タブを切りかえる
ボタンを押すと activeTab が入れかわり、p の中身がそのまま切りかわります。はじめはプロフィールが入っています。
表示中 プロフィール
setActiveTab("作品")押されたときに実行{activeTab}ここが入れかわる3 / 5
名前を取りちがえる
state が増えてくると、更新関数を取りちがえる事故が起きやすくなります。
setActiveTab に表示名の値を渡す
タブの表示が名前に化けてしまう
displayName の宣言を activeTab と離して書く
対応する組がひと目で分からなくなる
更新関数は set と値の名前でそろえ、宣言は関連する順にまとめておくと防げます。
4 / 5
考えてみよう外しても進めます
表示名を aoi に切りかえたあと、タブをプロフィールから作品に変えると、表示名はどうなりますか。
選ぶと、この枚の中で答えと理由を確かめられます。
5 / 5
直接書きかえは効かない
profile.title に代入しても、入れ物は同じままなので React は気づきません。
直接書きかえる
function promote() {
profile.title = "フロントエンド";
}新しいオブジェクトを渡す
function promote() {
setProfile({
...profile,
title: "フロントエンド",
});
}元のオブジェクトをスプレッドで写してから、変えたいキーだけ上書きします。
1 / 5
更新の落とし穴
オブジェクトの state を更新するとき、つまずきやすい書き方をまとめました。
スプレッドを書かず title だけのオブジェクトを渡す
name と bio が undefined になる
変えたいキーをスプレッドより前に書く
上書きが展開に消され、元の値に戻る
profile.title に直接代入する
画面が描き直されない
変えたいキーは、かならずスプレッドのうしろに書きます。
2 / 5
Reactで状態・フォーム・リストを扱う - オブジェクトのstate
丸かっこを忘れずに
更新関数に関数を渡す形でも、同じスプレッドが使えます。
波かっこをそのまま返すときは丸かっこで包みます。包まないと関数の本体だと読まれます。
function promote() {
setProfile((prev) => ({
...prev,
title: "フロントエンド",
}));
}3 / 5
Reactで状態・フォーム・リストを扱う - オブジェクトのstate
ageは残るか消えるか
setUser に渡す形を切り替えて、age の値が残るか消えるか確かめてください。
- スプレッドなしを選ぶと、age の行が消える
- スプレッドありを選ぶと、触っていない age がそのまま残る
- 画面の文字が undefined に変わる瞬間を見る
4 / 5
考えてみよう外しても進めます
変えたいキーをスプレッドより前に書くと、title の変更はどうなりますか。
選ぶと、この枚の中で答えと理由を確かめられます。
5 / 5
追加はスプレッドで
push は元の配列を書きかえるので、React は変化に気づきません。
pushで追加する
function addWork() {
works.push(newWork);
}スプレッドで追加する
function addWork() {
setWorks([...works, newWork]);
}スプレッドがいまの要素を全部展開し、そのうしろに新しい要素を並べます。
1 / 5
Reactで状態・フォーム・リストを扱う - 配列のstate
使ってよいメソッド
元の配列を変えるか、新しい配列を返すかで見分けます。
並べかえたいときは、まずスプレッドで写してから呼びます。
| メソッド | 新しい配列を返すか |
|---|---|
| map / filter / concat / slice | 返す。使ってよい |
| スプレッド [...arr, x] | 返す。使ってよい |
| push / pop / splice | 返さない。元を書きかえる |
| sort / reverse | 返さない。元を書きかえる |
2 / 5
配列更新の落とし穴
配列の state を更新するとき、つまずきやすい書き方をまとめました。
works.push で要素を足す
画面の一覧が増えない
push したあとに setWorks(works) を呼ぶ
同じ入れ物なので描き直されない
splice で並べかえや削除をする
元の配列が壊れ、ほかの場所にも影響する
更新関数に渡すのは、かならず新しく作った配列です。
3 / 5
Reactで状態・フォーム・リストを扱う - 配列のstate
画面のリストは増えるか
書き方を切り替えて、画面のリストに4件目が増えるか見てください。
- push を選ぶと、変数は増えるのに画面のマスは埋まらない
- setWorks に切りかえると、画面のマスまで埋まる
- つなぐ線がどこで止まるかを見くらべる
4 / 5
考えてみよう外しても進めます
id が3の作品だけを配列から取り除きたいとき、正しい書き方はどれですか。
選ぶと、この枚の中で答えと理由を確かめられます。
5 / 5
画面が変わるまでの3段
ボタンを押してから画面が変わるまで、React は毎回この3段を通ります。
きっかけ
更新関数が呼ばれ、stateが変わったとReactに伝わる
レンダリング
コンポーネント関数をもう一度呼び、新しいJSXを作る
反映
前の結果と見くらべ、違うところだけ書きかえる
大事なのは2段目です。関数をまるごと呼び直しています。
1 / 5
Reactで状態・フォーム・リストを扱う - 再レンダリングの仕組み
呼び直されるのを見る
コンポーネントの中に console.log を置くと、いつ呼ばれているか分かります。
押すたびにログが出ます。関数は毎回はじめから呼び直されています。
export default function App() {
const [likes, setLikes] = useState(0);
console.log("レンダリングされました");
return (
<button onClick={() => setLikes(likes + 1)}>
いいね {likes}
</button>
);
}2 / 5
Reactで状態・フォーム・リストを扱う - 再レンダリングの仕組み
同じ値と違う値
手順を1つずつ進め、同じ値をセットするとどう変わるか比べてください。
- 手順を進めると、3段のどこまで進んだかが色で分かる
- 同じ値をセットすると、3段目で書きかわるところが無くなる
- 違う値のときだけ画面の数字が入れかわる
3 / 5
描き直しの落とし穴
レンダリングの仕組みでつまずきやすい書き方をまとめました。
setLikes(likes) といまと同じ値を渡す
変化なしと判断され、見た目は変わらない
クリックのたびに useState(0) の行も実行される
それでも likes は0に戻らず、前の値のまま描き直される
return の手前で直接 setLikes を呼ぶ
描き直しがまた描き直しを呼び、止まらなくなる
更新関数を呼ぶのは、イベントの中だけです。
4 / 5
考えてみよう外しても進めます
いまと同じ値をセットするボタンを2回押すと、画面のいいね数は変わりますか。
選ぶと、この枚の中で答えと理由を確かめられます。
5 / 5
Reactで状態・フォーム・リストを扱う - イベントハンドラ
呼ばれ方の名前
onClick 以外も同じ形です。名前はキャメルケース、値は関数です。
先頭を小文字にした onclick は React に認識されません。
| 名前 | 何のとき |
|---|---|
| onClick | クリックされたとき |
| onChange | 入力欄の中身が変わったとき |
| onSubmit | フォームが送信されたとき |
| onMouseEnter | マウスが乗ったとき |
1 / 5
引数を渡したいとき
かっこを付けたい気持ちは、アロー関数で包んで満たします。
その場で呼ばれる書き方
onClick={addLike(3)}アロー関数で包む書き方
onClick={() => addLike(3)}左は描画のたびに addLike(3) が走り、押しても反応しません。
2 / 5
Reactで状態・フォーム・リストを扱う - イベントハンドラ
もう一度確かめる
かっこを付けると何回押しても増えないままか、動かして確かめてください。
- 押した回数を動かすと、画面の数字がそのぶん増える
- onClick に かっこ を付けると、回数を増やしても数字が動かない
- 結論の帯が朱に変わったら、動かなくなっている合図
3 / 5
詰まりやすい3つ
書き方の形だけ似ていて、動くものと動かないものが混ざります。
onclick と全部小文字で書く
React が認識せず何も起きない
onClick={addLike(3)} とそのまま書く
描画のたびに呼ばれ、押しても反応しない
ハンドラをコンポーネントの外に書く
state を更新する関数に手が届かない
動かないときは、まずこの3つを疑ってください。
4 / 5
考えてみよう外しても進めます
3増やすボタンを作ります。onClick に何を渡せば、押したときだけ addLike(3) が走りますか。
選ぶと、この枚の中で答えと理由を確かめられます。
5 / 5
eが運ぶ情報の道
onClick={handleSelect} と渡すだけで、押されたときに e が届きます。
押す
ボタンがクリックされる
呼ばれる
React が handleSelect(e) を呼ぶ
target
e.target が押された要素になる
dataset
data-title の値を取り出す
引数を書かなくても、React が e を渡してくれます。
1 / 5
Reactで状態・フォーム・リストを扱う - イベントオブジェクト
値の道をたどる
読む場所を切り替えて、入力された文字にたどり着く道を探してください。
- e.target.value を選ぶと、入力欄まで矢印がつながる
- e.value を選ぶと道が外れて undefined になる
- 入力欄を空にすると、届く値も空の文字列に変わる
2 / 5
中に要素があるとき
ボタンの中に span を入れて span を押すと、target と currentTarget がずれます。
target 押された要素そのもの
span を押すと target は span になり、data-title が読めない
currentTarget 付けた要素
ハンドラを付けた button のままなので、data-title が読める
中に別の要素を入れないなら、target のままで問題ありません。
3 / 5
3つのボタンの結果
同じ handleSelect が、押されたボタンによって違う値を受け取ります。
e.target.dataset.title押された要素の data-title結果
| 押したボタン | selected |
|---|---|
| work-1 | レシピ検索アプリ |
| work-2 | 買い物メモツール |
| work-3 | 写真ギャラリー |
4 / 5
考えてみよう外しても進めます
ボタンの中に span があり、span を押しました。data-title を確実に読むにはどちらを使いますか。
選ぶと、この枚の中で答えと理由を確かめられます。
5 / 5
入力欄をstateにつなぐ
value で state の中身を映し、onChange で打った文字を state へ戻します。
こんにちは、あおい さん
value={name}stateを映すsetName(e.target.value)打った文字をstateへ戻す1 / 5
Reactで状態・フォーム・リストを扱う - 制御されたinput
stateと画面をつなぐ輪
打った文字数を動かして、上の state と下の入力欄が同じ文字になるか確かめてください。
- 文字数を動かすと、上の state と下の入力欄が同時に変わる
- クリアボタンを押すと、state も画面も一緒に空になる
- value と onChange の輪が、常に同じ文字を行き来している
2 / 5
片方だけだと壊れる
value と onChange は2つで1組です。片方が欠けると事故が起きます。
value だけ書き、onChange を書かない
打っても state が変わらず、入力欄が固まる
onChange だけ書き、value を書かない
state は更新されても、表示は入力欄任せのまま食い違う
value と onChange は2つで1組と覚えてください。
3 / 5
Reactで状態・フォーム・リストを扱う - 制御されたinput
初期値は空文字にする
useState に何も渡さないと、最初の value が undefined になります。
最初は undefined で、打った瞬間に文字列へ変わります。React はこれを警告するので、空の文字列を渡してください。
const [name, setName] = useState();
<input value={name} onChange={h} />4 / 5
考えてみよう外しても進めます
input に value={name} だけを書いて onChange を書かないと、何を打ってもどうなりますか。
選ぶと、この枚の中で答えと理由を確かめられます。
5 / 5
Reactで状態・フォーム・リストを扱う - 複数の入力
欄の数だけstateを増やす
増えるのは欄の数だけです。欄1つにつき state 1つ、value と onChange を1組ずつ用意します。
やることは前回の input と変わりません。
| 欄 | state |
|---|---|
| 名前 input | name / setName |
| ご用件 select | kind / setKind |
| 本文 textarea | body / setBody |
1 / 5
textareaもselectも同じ
テキストエリアもセレクトも、value と onChange の組で state とつなぎます。
<select value={kind}selectもvalueで見せる<textarea value={body}textareaもvalueで渡す2 / 5
Reactで状態・フォーム・リストを扱う - 複数の入力
壊れ方はどの欄も同じ
onChange を消して、押したキーが入力欄に届かなくなる様子を確認してください。
- onChange があるうちは、押したキーがそのまま state と入力欄に届く
- onChange を消すと、キーを押しても state が更新されない
- この壊れ方は input にかぎらず、textarea や select でも同じように起きる
3 / 5
textareaとselectの罠
欄の種類ごとに、書き方を間違えやすい点があります。
textarea の中身を子要素として書く
React が警告を出す。中身は value で渡す
option に selected を書く
React が警告を出す。選択状態は select の value で決まる
select の初期値は、option のどれかの value と同じ文字列にします。
4 / 5
考えてみよう外しても進めます
select で最初に選択状態にしたい項目があるとき、正しいのはどれですか。
選ぶと、この枚の中で答えと理由を確かめられます。
5 / 5
止めないとstateが消える
左は既定のまま、右は preventDefault で止めています。既定のままだと送信のたびにページが読み込み直され、state がすべて初期値に戻ります。
既定のまま
<form>
<input value={name}
onChange={h} />
<button type="submit">送信</button>
</form>onSubmitで止める
function handleSubmit(e) {
e.preventDefault();
setSent(name + "さんから受領");
}
<form onSubmit={handleSubmit}>
...
</form>1 / 5
Reactで状態・フォーム・リストを扱う - フォーム送信
送信ボタンを押し比べる
上と下で同じ送信を押して、入力した文字が残るか確かめてください。
- そのまま送信を選ぶと、入力した文字が消えて再読み込みになる
- preventDefault を選ぶと、再読み込みが起きず文字が残る
- 止めているのは送信そのものではなく、ページの再読み込みだけ
2 / 5
Reactで状態・フォーム・リストを扱う - フォーム送信
Enterでも送信は起きる
きっかけによって、onClick と onSubmit の呼ばれ方が違います。
Enter からの送信も止めたいので、ハンドラは form の onSubmit に付けます。
| きっかけ | 呼ばれるハンドラ |
|---|---|
| 送信ボタンをクリック | onClick も onSubmit も呼ばれる |
| 入力欄で Enter を押す | onClick は呼ばれず、onSubmit だけ呼ばれる |
3 / 5
集める処理はいらない
入力欄はすでに state と同期しているので、送信時に値を集める処理は要りません。state をそのまま読むだけです。
name +stateをそのまま読む呼び出しと結果
| state | 値 |
|---|---|
| name | あおい |
| body | サイト制作のご相談です |
| sent | あおいさんから受領 |
4 / 5
考えてみよう外しても進めます
入力欄で Enter キーを押したとき、form の送信は起きますか。
選ぶと、この枚の中で答えと理由を確かめられます。
5 / 5
チェックの有無で変わる
左は判定なし、右は空なら送信を止めています。
チェック無し
function handleSubmit(e) {
e.preventDefault();
setSent(name + "さんから受領");
}チェックあり
function handleSubmit(e) {
e.preventDefault();
if (name.trim() === "") {
setError("入力してください");
return;
}
setError("");
setSent(name + "さんから受領");
}1 / 5
Reactで状態・フォーム・リストを扱う - バリデーション
送信の分かれ道
文字数を0にして、送信の枝とメッセージの枝を確かめてください。
- 文字数を0にすると、送信ではなくメッセージの枝に色が付く
- チェックを外すと、空のまま送信の枝を素通りしてしまう
- 分かれ道の判定は、入力が空かどうかだけを見ている
2 / 5
止める・確かめる・消す
handleSubmit の中でやることは、この3手です。
止める
e.preventDefault() を呼ぶ
確かめる
空なら setError して return する
消す
通ったときは空文字を渡してエラーを消す
この順番を崩すと、エラーと結果が同時に出るような食い違いが起きます。
3 / 5
つまずきどころ
バリデーションでよくある3つのミスです。
if の中で return を書き忘れる
エラーを出したのに送信処理まで進む
通過したときにエラーを消し忘れる
成功してもエラー文が残ったまま
空白だけの入力を見ない
スペース1つでも未入力扱いにならない
3つとも、エラーの状態が中途半端に残る詰まり方です。
4 / 5
考えてみよう外しても進めます
if の中で setError を呼んだあと、return を書き忘れるとどうなりますか。
選ぶと、この枚の中で答えと理由を確かめられます。
5 / 5
手書きをmapにする
3枚を手でコピーする代わりに、配列から作ります。
手でコピー
<div className="work-card">
<h2>レシピ検索アプリ</h2>
</div>
<div className="work-card">
<h2>買い物メモツール</h2>
</div>works.mapで作る
{works.map((work) => (
<div className="work-card">
<h2>{work.title}</h2>
</div>
))}作品が増えても、書きかえるのは配列だけです。
1 / 5
Reactで状態・フォーム・リストを扱う - mapでリスト描画
1件が1枚のカードに
works の件数を変えてから、1件ずつ描くを進めてください。
- 件数を0にすると、画面のカードも0枚のまま
- 1件ずつ描くを進めた回数だけ、カードが増える
- 件数を4にすると、並ぶカードもちょうど4枚になる
2 / 5
描かれない2つの理由
配列から一覧を描くとき、つまずきやすいのはこの2つです。
forEach で一覧を描こうとする
戻り値が undefined で、1件も描かれない
波かっこの中に if 文をそのまま書く
文は式ではないので使えない。出し分けはこの先の回で扱う
画面に一覧を出せるのは map だけです。
3 / 5
画面に3枚のカード
map が返した JSX を、そのままブラウザが描画します。書いたコードと画面の対応を確認してください。
レシピ検索アプリ
買い物メモツール
写真ギャラリー
works.map1件ずつ変換する4 / 5
考えてみよう外しても進めます
works.map の代わりに forEach を使って一覧を描こうとすると、どうなりますか。
選ぶと、この枚の中で答えと理由を確かめられます。
5 / 5
keyはどこに付けるか
map が返す一番外側の要素に、key を付けます。
keyが無い
{works.map((work) => (
<div className="work-card">
<h2>{work.title}</h2>
</div>
))}keyを付ける
{works.map((work) => (
<div className="work-card"
key={work.id}>
<h2>{work.title}</h2>
</div>
))}中の h2 に付けても警告は消えません。
1 / 5
Reactで状態・フォーム・リストを扱う - key
keyが無いとずれる
先頭の1件を消して、入力した数字がどの行に残るか確かめてください。
- key を付けずに消すと、入力した数字が別の行へずれる
- key を付けてから消すと、数字は同じ行に残ったまま
- コードは正しく見えるのに、入力だけがずれるのがこの図の要点
2 / 5
keyにしてはいけない値
一意で、かつ変わらない値を選びます。
配列の添字を key にする
先頭に1件足すと全部の添字がずれ、印の役目を失う
work.title のように変わる値を key にする
値が変わるたびに別のものとして扱われ、作り直しが増える
毎回変わる乱数を key にする
描くたびに別の値になり、全部作り直される
今回のデータなら work.id が最適です。
3 / 5
Reactで状態・フォーム・リストを扱う - key
keyは画面には出ない
同じ id でも、出力のされ方が違います。
確認したいときは data- 属性を別に付けます。
| 書き方 | HTMLへの出力 |
|---|---|
| key={work.id} | 出力されない。React だけが見る印 |
| data-work-id={work.id} | そのまま div の属性として出力される |
4 / 5
考えてみよう外しても進めます
先頭に新しい作品を1件追加する一覧で、key に配列の添字を使うと何が起きますか。
選ぶと、この枚の中で答えと理由を確かめられます。
5 / 5
出さないだけなら
出すか出さないかの1択には、三項演算子で null を書くより論理積のほうが素直です。
三項演算子 + null
{work.year >= 2026
? <span className="badge-new">NEW</span>
: null}論理積だけで書く
{work.year >= 2026 &&
<span className="badge-new">NEW</span>}右にJSXを1つ置くだけで、左が偽のときは何も描かれません。
1 / 5
Reactで状態・フォーム・リストを扱う - 条件レンダリング(&&)
消えるのはいつか
count を動かして、右の要素がいつ画面から消えるか確かめてください。
- count を0にすると、右の要素ごと画面から消える
- 比較を外して count だけにすると、0のとき数字の0が画面に残る
- 論理積は真偽値ではなく、左か右の値そのものを返す
2 / 5
Reactで状態・フォーム・リストを扱う - 条件レンダリング(&&)
Reactは値をどう描くか
式が返した値を、React は種類によって描いたり描かなかったりします。
false と 0 は同じ偽でも、画面での扱いが違います。
| 返ってきた値 | 画面での扱い |
|---|---|
| false / null / undefined | 何も描かない |
| 0 | そのまま数字を描く |
| 空の文字列 | 何も描かない |
| JSXの要素 | その要素を描く |
3 / 5
JSXならではの穴
論理積を条件表示で使うときによくある2つのつまずきです。
右にJSXを2つ並べて書く
1つの式にならず構文エラーになる
出ない側にも何か出したくて論理積を使う
偽のときは常に空白のまま。両方に出すなら三項演算子
論理積は、出すか出さないかの専用です。
4 / 5
考えてみよう外しても進めます
2025年の作品にはバッジを出したくありません。論理積の左に置くのはどれですか。
選ぶと、この枚の中で答えと理由を確かめられます。
5 / 5
Reactで状態・フォーム・リストを扱う - 出し分け(三項)
必ずどちらかが出る
ok を切り替えて、必ずどちらかの枝だけが画面に降りるのを確かめてください。
- ok を切り替えると、光る枝が入れ替わる
- JSX の中で if 文を使うを入れると、構文エラーで画面が消える
- 三項演算子はどちらの枝を選んでも、必ず1つの値を返す
1 / 5
文字も色も出し分ける
同じ三項演算子で、文字だけでなく className も出し分けられます。表示は右のようになります。
? "label-public"属性の値も出し分け2 / 5
Reactで状態・フォーム・リストを扱う - 出し分け(三項)
2つの書き方の使い分け
同じ出し分けでも、出ない側に何を出すかで使う書き方が変わります。
迷ったら、出ない側に何を出すかを考えます。
| やりたいこと | 使う書き方 |
|---|---|
| 出すか、出さないかの1択 | 論理積 |
| どちらかを必ず出す2択 | 三項演算子 |
| 文字列や className の出し分け | 三項演算子 |
3 / 5
入れ子はやめどき
三項演算子を重ねすぎると、条件がどこにかかるか読めなくなります。
三項演算子を2段以上入れ子にする
条件がどこにかかるか読めなくなる
3段を超えてもJSXの中で粘る
変数に分けたほうが早いのに時間を溶かす
3段を超えたら、return の前で if 文を使い、変数にJSXを入れてから出します。
4 / 5
考えてみよう外しても進めます
公開中と非公開で背景色まで変えたいとき、一番素直な書き方はどれですか。
選ぶと、この枚の中で答えと理由を確かめられます。
5 / 5
0件を比較で判定する
件数をそのまま論理積の左に置くと、0件のとき画面に0という文字が出ます。比較にすれば真偽値になり、事故が起きません。
件数をそのまま置く
{works.length && (
<p>作品があります</p>
)}比較で出し分ける
{works.length === 0 ? (
<p className="empty-message">
まだ作品がありません
</p>
) : (
works.map((work) => ...)
)}1 / 5
Reactで状態・フォーム・リストを扱う - 空状態
0件のときの枝
件数を0まで減らして、通る枝がどこで切り替わるか追ってください。
- 件数を0にすると、通る枝が空状態のほうへ切り替わる
- 0件のときの枝を消すと、画面が空のまま何も出なくなる
- 件数が0かどうかの判定は、この分かれ道と同じ形をしている
2 / 5
空状態のつまずき
0件の表示でよくある3つのミスです。
件数をそのまま論理積の左に置く
0件のとき画面に0の文字が出る
0件のときの分岐を書かない
見出しの下が空のままになる
空状態に文言だけ書く
次に何をすればよいか伝わらない
空状態には、なぜ空なのかと次の一歩まで書きます。
3 / 5
空のときの画面
works が空の配列のとき、三項演算子の右側ではなく左側が描かれます。
まだ作品がありません
works.length === 00件かどうかで分かれる4 / 5
考えてみよう外しても進めます
三項演算子で 件数が0か ? A : B と書いたとき、0件のとき描かれるのはどちらですか。
選ぶと、この枚の中で答えと理由を確かめられます。
5 / 5
絞った配列は持たない
絞り込んだあとの配列まで state にすると、元データを1件足すたびに両方を直す必要が生まれます。
絞込み後をstateにする
const [shown, setShown] = useState(works);
// works を1件足したら
// shown も書きかえないと食い違う毎回計算する
const shown =
category === "all"
? works
: works.filter(
(w) => w.category === category
);state に置くのは、元データと選ばれているカテゴリの2つだけです。
1 / 5
Reactで状態・フォーム・リストを扱う - 絞り込みUI
絞ってから並べる
2段を進めて、絞ってから並べる順番を確かめてください。
- 1段目で条件に合わない行が線で消え、次の段に進まない
- しきい値を上げると1件も残らず、カードが0枚になる
- 画面のカードの枚数は、絞り込みで残った件数と同じになる
2 / 5
絞り込みのつまずき
カテゴリ絞り込みでよくある3つのミスです。
onClick に更新関数の呼び出しを直接書く
描画した瞬間に呼ばれ、更新が終わらない
並べる対象を元の配列のままにする
絞り込んでも一覧の中身が変わらない
件数を元の配列の長さで出す
絞り込んでも表示件数が動かない
件数もカードも、かならず絞り込んだあとの配列から出します。
3 / 5
選択中を見せる
className を三項演算子で出し分けると、選ばれているボタンだけ見た目が変わります。
is-active選ばれているときだけ付く4 / 5
考えてみよう外しても進めます
カテゴリ絞り込みの画面で、state に置くべきものはどれですか。
選ぶと、この枚の中で答えと理由を確かめられます。
5 / 5
