ポケモンで学ぶPropsとState
React の Props(プロップス)と State(ステート)は、React でウェブアプリケーションを作る時に大切な概念です。
ポケモンのゲームを例に説明していきます。
Props(プロップス)
Props は、React のコンポーネントに渡されるデータです。
これは親コンポーネントから子コンポーネントへと渡されます。
Props は読み取り専用で、コンポーネント内で変更することはできません。
例
ポケモンのゲームで考えると、あるポケモントレーナー(親コンポーネント)が自分のポケモン(子コンポーネント)に指示(Props)を出すようなものです。
トレーナーはポケモンに「たたかう」や「にげる」といった指示を出しますが、ポケモン自身がこの指示を変えることはできません。
State(ステート)
State は、コンポーネント内で管理されるデータです。
これはコンポーネント内で変更することができ、変更されるとコンポーネントは再レンダリングされます。
例
ポケモンのゲームで考えると、ポケモン自身の体力や状態異常などが State にあたります。
バトル中にポケモンがダメージをうけると体力(State)が減りこれによって、表示される体力バーが変化します。
実際のコード例
ここでは、React を使って簡単なポケモン関連のコンポーネントを作成してみます。
import React, { useState } from 'react';
// ポケモンコンポーネント
const Pokemon = ({ name, initialHp }) => { //propsの名前は一般的にキャメルケース(camelCase)記法
const [hp, setHp] = useState(initialHp); // State: 体力
// 体力を減少させる関数
const takeDamage = () => {
setHp(hp - 10);
};
return (
<div>
<h2>{name}</h2>
<p>体力: {hp}</p>
<button onClick={takeDamage}>ダメージを受ける</button>
</div>
);
}
// トレーナーコンポーネント
const Trainer = () => {
return (
<div>
<h1>ポケモントレーナー</h1>
<Pokemon name="ピカチュウ" initialHp={100} /> {/* Propsを渡す */}
</div>
);
}
export default Trainer;
このコードでは、Trainer コンポーネント(親)が Pokemon コンポーネント(子)に名前(name)と初期体力(initialHp)という Props を渡しています。
ポケモンコンポーネントは、自分の体力(hp)を State として持ち、ダメージを受けるたびにこれを更新します。
実際に、以下のような動きになります。
補足
コンポーネントの更新タイミング
コンポーネントで再描画がおこなわれるのは主に以下のタイミングです。
- Stateが更新された場合
- 渡されたPropsが変更された場合
- 親コンポーネントが再描画された場合
Props と引数の違い
Props は React コンポーネントで使われる特別な種類の「引数」のようなものです。
しかし、Props はその性質と使用法において、一般的な関数の引数とは異なる特徴を持っています。
useState
const [hp, setHp] = useState(initialHp)
というコードは、React のフック(Hook)であるuseState
を使用しています。
この構造では、コンポーネントの「状態」を管理するために使われます。
役割
useState
は、コンポーネント内で状態(State)を作成・管理するためのフックです。
状態とは、コンポーネントのデータや情報のことで、このデータが変わるとコンポーネントは再レンダリングされます。
構文と構造
-
useState(initialHp)
の呼び出し
ここでは、useState
を呼び出し、初期値のinitialHp
を渡しています。
initialHp
はこの状態の初期値です。
例えば、ポケモンの初期体力を 100 に設定したい場合はinitialHp
に 100 を渡します。 -
配列分割代入:
const [hp,setHp] = useState(initialHp)
上記の部分で行われているのは、配列分割代入です。
useState
は 2 つの要素を持つ配列を返します。
1 つ目の要素は現在の状態(この例では、hp
)、2 つ目の要素はその状態を更新するための関数(この例では、setHp
)です。
動作の流れ
- 1.初期化
コンポーネントが最初にレンダリングされるとき、useState
に渡された値(initialHp
)がhp
の初期値として設定されます。 - 2.状態の読み取り
コンポーネント内で、hp
を使うと、現在の体力の値が得られます。 - 3.状態の更新
setHp
関数で呼び出すことで、hp
の値を更新できます。
例えばsetUp(hp - 10)
を実行すると、現在のhp
から 10 減った値が新しいhp
になります。 - 4.再レンダリング
hp
が更新されると、コンポーネントは自動的に再レンダリングされ、最新のhp
の値が画面に表示されます。
アロー関数
const takeDamage = () => { setHp(hp - 10); };
という記述はアロー関数(Arrow Function)を使用したものです。
アロー関数の基本
アロー関数は以下のような構文で記述されます。
const functionName = (引数) => {
//関数の本体
}
この場合、takeDamage
は関数名で、アロー(=>
)の左側には引数がきます。
今回の場合は、引数はありません。
アローの右側には関数の本体が記述されます。
アロー関数と const の組み合わせ
アロー関数は、const
と組み合わせてよく使われます。
これにより、変数に関数式を割り当てることができます。
この方法で定義された関数は、「匿名関数」として知られています。
Discussion