React入門 - 6. stateの使い方
6. stateの使い方
引き続きReactの関数コンポーネントの学習を続けていきましょう。次は状態をもつ関数コンポーネントについて取り上げます。一般的に、関数といえば引数で受け取ったデータを処理して結果を返すものであり、状態には依存しないものです。たとえば次の double
関数は、引数の値を2倍にした値を返します。
function double(value) {
return value * 2;
}
この double
関数を double(3)
のように引数に 3
を指定して呼び出すと、戻り値は必ず 6
になります。関数の状態に依存して結果が 5
になったり、7
になったり、ということはありえません。このように引数だけで結果が決まる関数を純粋関数(pure function) などと呼びます。
厳密には関数呼び出しの副作用がないことも純粋関数の条件の一部です。
Reactの関数コンポーネントに話を戻しましょう。関数コンポーネントは名前の示すとおり、関数で定義されたコンポーネントです。そのため props
を使ってデータを引数として、受け取ることはできますが、状態( state
)を利用することができない、という制約が以前はありました。そのため、状態に依存するコンポーネント(ステートフルなコンポーネント)を定義する場合は、クラスコンポーネントを作成する必要がありました。
しかし、現在の関数コンポーネントには Hooks
という仕組みがサポートされています。Hooks
とは関数コンポーネントに状態管理などの様々な機能を追加する仕組みです。この Hooks
という仕組みを使うことで関数コンポーネントでも簡単に状態( state
)を管理できるようになります。
Reactでは状態を
state
と呼びます。
useState 関数
それでは実際に状態を持つ関数コンポーネントを定義してみましょう。ここではボタンのクリック回数を表示する Counter
コンポーネントを作成してみます。Counter
コンポーネントではボタンをクリックした回数を状態( state
)として管理します。次のプログラムを src
フォルダに Counter.js
という名前で作成します。
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={e => setCount(count + 1)}>increment</button>
</div>
)
}
export default Counter;
Counter
コンポーネントは関数コンポーネントであるため funciton
キーワードで関数を定義しています。また関数の内部ではJSXを使って出力するタグを定義しています。これまでの関数コンポーネントと異なるのは以下の部分です。
const [count, setCount] = useState(0);
ここではReactに用意されている useState
関数を利用しています。これはステートフック(State Hook)と呼ばれるもので関数コンポーネントに状態を定義する際に利用するものです。
useState
関数は状態管理したいデータを引数で受け取ります。今回は ボタンのクリック回数 を状態として管理したいので、useState
関数の引数に 0
を指定しています。また useState
関数は戻り値で配列を返却します。戻り値となる配列の先頭要素は、現在の状態を表すデータであり、2番目の要素は状態を更新するために関数オブジェクトです。このプログラムの場合、変数 count
にクリック回数を代入していて、setCount
変数にクリック回数を更新する関数オブジェクトを代入しています。
useState
関数はreact
パッケージで定義されています。そのためプログラムの先頭部分でimport
宣言を追加しています。import
宣言は手入力せずにテキストエディタの補完機能を使うようにします。
次にJSXの定義を見てみましょう。
<div>
<p>Count: {count}</p>
<button onClick={e => setCount(count + 1)}>increment</button>
</div>
ここでは <p>
タグの中で先ほど useState
関数で取得した変数 count
を出力しています。変数 count
はクリック回数を表す状態( state
)です。初期値は 0
ですが後の increment
ボタンがクリックされるたびに状態が更新されて、出力が変化します。次に <button>
タグの定義部分では onClick
プロパティにイベントハンドラを無名関数で定義しています。
<button onClick={e => setCount(count + 1)}>increment</button>
onClickプロパティには、イベントオブジェクト(上記の変数 e
)を引数にとる関数を指定できます。ここで定義した関数では、 先の useState
関数の戻り値である setCount
関数を使って状態(クリック回数)をインクリメントしています。
Reactの
state
の更新は必ず専用の関数(この場合、setCount
)を使う必要があります。count
変数を直接更新するのではない、という点に注意していください。
App.js
つづいて作成した Counter
コンポーネントを親コンポーネントである App.js
に追加してみましょう。
import './App.css';
import Counter from './Counter';
import Hello from './Hello';
function App() {
return (
<>
<Hello name="React" />
<Counter />
</>
);
}
export default App;
ここでは Hello
コンポーネント定義のあとに Counter
コンポーネントを追記しています。またReactの関数コンポーネントは必ず1つのルートコンポーネントを持つ必要があるため、ここではフラグメント <></>
を宣言しています。
<>
<Hello name="React" />
<Counter />
</>
もしフラグメントを使わずに以下のように関数コンポーネントを定義すると、コンパイラはエラーを検出します。
function App() {
return (
<Hello name="React" />
<Counter />
);
}
このようにコンポーネント定義時にはいくつかの制約にしたがう必要があります。
動作確認
それではブラウザからアクセスして動作を確認しておきましょう。 npm start
によって開発サーバを起動した状態で、ブラウザを開いて http://localhost:3000 にアクセスすると次のような結果を確認できるでしょう。
上記のように <Hello name="React" />
コンポーネントの出力の後に <Counter />
コンポーネントの出力結果を確認できるでしょう。また表示された increment
ボタンをクリックすると数値が加算されていく様子を確認できます。
実行結果から Counter
コンポーネントがボタンをクリックした回数を状態( state
)として管理できていることがわかります。
関数コンポーネントとHooks
Reactには class
を使ったコンポーネントの定義方法(クラスコンポーネント)と、function
を使ったコンポーネントの定義方法(関数コンポーネント)の2つが用意されています。2022.3月現在においてはクラスベースでもコンポーネントも定義できますが、関数コンポーネントを使うことが主流になってきています。その理由は関数コンポーネントに Hooks
という仕組みが導入されたからです。
関数コンポーネントにはReactの Hooks
という仕組みを利用することで、 useState
関数で状態管理機能を追加できることを学びました。Hooks
には状態管理機能を追加する以外にも、コンポーネントの副作用(データの取得処理など)を定義する useEffect
といった関数も用意されています。これらの機能を必要に応じて、コンポーネントにフックする(ひっかける)ことで、クラスベースのコンポーネントと同様の機能を使って開発を進めることができます。
2022.3月時点時点では、一部の機能はクラスベースでしか扱えないものあるようです。
まとめ
本講座ではNode.jsのインストールから create-react-app
によるReactプロジェクトの作成方法、それからコンポーネントの作成方法について解説しました。
Reactはユーザインタフェースを構築するライブラリです。関数コンポーネントやJSXのような仕組みを使って画面を構成するコンポーネントを宣言的に定義します。宣言的に定義されたReactのコンポーネントは状態の変化を検出すると自動的に画面を再描画します。Reactのコンポーネントは親コンポーネントから子コンポーネントへデータを受け渡すために props
を使います。またコンポーネント内で状態を管理するために state
を使います。まずはコンポーネントの基本的な仕組みである props
や state
の使い方に慣れていくことがReact学習のポイントになります。