インタラクティブ性の追加
画面上の一部の要素は、ユーザーの入力に応じて更新されます。例えば、画像ギャラリーをクリックするとアクティブな画像が切り替わります。Reactでは、時間とともに変化するデータをstate(状態)と呼びます。どのコンポーネントにもstateを追加し、必要に応じて更新できます。この章では、インタラクションを処理し、stateを更新し、時間の経過とともに異なる出力を表示するコンポーネントの書き方を学びます。
イベントへの応答
Reactでは、JSXにイベントハンドラーを追加できます。イベントハンドラーは、クリック、ホバー、フォーム入力へのフォーカスなどのユーザーインタラクションに応答してトリガーされる独自の関数です。
<button>のような組み込みコンポーネントは、onClickのような組み込みのブラウザイベントのみをサポートしています。ただし、独自のコンポーネントを作成し、そのイベントハンドラープロップに任意のアプリケーション固有の名前を付けることもできます。
このトピックを学ぶ準備はできていますか?
詳細を読むイベントへの応答を読んで、イベントハンドラーの追加方法を学びましょう。
State:コンポーネントの記憶
コンポーネントは、インタラクションの結果として画面上の表示を変更する必要がよくありますstate(状態)
useStateフックを使用してコンポーネントにstateを追加できます。フックは、コンポーネントがReactの機能(stateはその機能の1つ)を使用できるようにする特別な関数です。useStateフックを使用すると、state変数を宣言できます。これは初期状態を受け取り、現在の状態とそれを更新するためのstateセッター関数のペアを返します。
レンダーとコミット
コンポーネントが画面に表示される前に、Reactによってレンダーされる必要があります。このプロセスのステップを理解することで、コードの実行方法について考え、その動作を説明できるようになります。
コンポーネントを厨房で材料から美味しい料理を組み立てる料理人と想像してください。このシナリオでは、Reactは客からの注文を受け付け、料理を運ぶウェイターです。UIを要求して提供するこのプロセスには3つのステップがあります:
- トリガー(客の注文を厨房に届ける)
- レンダー(厨房で注文を準備する)
- コミット(注文をテーブルに置く)
トリガー
レンダー
コミット
イラスト:Rachel Lee Nabors
スナップショットとしてのstate
通常のJavaScript変数とは異なり、Reactのstateはスナップショットのように振る舞います。stateを設定しても、既存のstate変数が変更されるのではなく、代わりに再レンダーがトリガーされます。これは最初は驚くかもしれません!
この動作は、微妙なバグを避けるのに役立ちます。ここに小さなチャットアプリがあります。最初に「送信」を押して、その後受信者をBobに変更するとどうなるか、推測してみてください。5秒後にalertに誰の名前が表示されるでしょうか?
一連のstate更新をキューに入れる
このコンポーネントにはバグがあります:「+3」をクリックしてもスコアは1回しか増えません。
スナップショットとしてのstateで、これが起こる理由を説明しています。stateを設定すると新しい再レンダーが要求されますが、すでに実行中のコード内では変更されません。したがって、scoreは0のままです。setScore(score + 1)を呼び出した直後でも同様です。
この問題は、状態を設定する際に更新関数を渡すことで修正できます。setScore(score + 1)をsetScore(s => s + 1)に置き換えると、「+3」ボタンが修正されることに注目してください。これにより、複数の状態更新をキューに入れることができます。
状態内のオブジェクトを更新する
状態は、オブジェクトを含むあらゆる種類のJavaScriptの値を保持できます。しかし、Reactの状態に保持しているオブジェクトや配列を直接変更すべきではありません。代わりに、オブジェクトや配列を更新したい場合は、新しいものを作成する(または既存のもののコピーを作成する)必要があり、その後、そのコピーを使用するように状態を更新します。
通常、変更したいオブジェクトや配列をコピーするには、...スプレッド構文を使用します。例えば、ネストされたオブジェクトの更新は次のようになります:
コード内でオブジェクトをコピーするのが面倒な場合は、Immerのようなライブラリを使用して繰り返しのコードを減らすことができます:
ステート内の配列の更新
配列は、ステートに保存できるもう一つのミュータブルなJavaScriptオブジェクトであり、読み取り専用として扱うべきです。オブジェクトと同様に、ステートに保存された配列を更新したい場合は、新しい配列を作成する(または既存の配列のコピーを作成する)必要があり、その後、ステートを新しい配列を使用するように設定します:
コード内で配列をコピーするのが面倒な場合は、Immerのようなライブラリを使用して繰り返しのコードを減らすことができます:
次は何をしますか?
この章をページごとに読み始めるには、イベントへの応答に進んでください!
または、これらのトピックにすでに精通している場合は、状態の管理について読んでみませんか?
