はじめに
Reactは、ユーザーインターフェースを構成するためのJavaScriptライブラリです。近年では、ウェブアプリケーションやモバイルアプリケーションのインターフェースを作成するために、多くの開発現場で使用されています。Reactを学ぶことで、モダンなウェブ開発のスキルを身につけることができるため、フロントエンドエンジニアを目指す上で必須のスキルと言っても過言ではありません。
フロントエンドエンジニアを目指す方や、初めてReactを学ぶ方に向けて、この記事ではReact Hooksの中でも使用頻度の高いuseStateについて解説します。コンポーネントの状態管理は、アプリケーションを構成する上で必須の知識です。useStateの基本を押さえておくことで、これからのReact学習の理解度が深まります。基本を学び、フロントエンドエンジニアへの道を進んでいきましょう!
この記事について
目的
- useStateについて知る
- useStateを使用した状態管理ができるようにする
対象者
- 初学者の方
- Reactの勉強を最近始めた方
- stateの管理に苦手意識のある方
Reactの基本について
Reactの基本の説明はこの記事では省略しています。基本や環境構築方法などを知りたい方は、下記のページをご覧ください。
https://envader.plus/article/341
useStateに関する基本情報
useStateとは
useStateとは、Reactの関数コンポーネントの中で状態を管理するためのReact Hooksの1つです。コンポーネントが状態を持つことで、ユーザーの操作やその他のイベントによって画面の表示内容を変化させることができます。「コンポーネントが状態を持つ」というのは、コンポーネント内の変数にデータを保持できるということです。これにより、ユーザーが操作したデータの変更に即座に反応し、画面の表示内容を動的に変化させることが可能になります。
例えば、以下のようなアプリでは、ボタンをクリックするたびにコンポーネント内の変数が更新され、表示される数字が変化します。これは、コンポーネントが状態を管理し、データの変更内容を画面に再表示することで実現されています。
state(状態)とは
state(状態)とは、ユーザー操作などにより変更されるデータを保存する変数のことを指します。コンポーネント内で特定のデータを管理し、そのデータが変化することによって画面の表示内容を動的に変更できます。例えば、ボタンをクリックした回数、入力フォームに入力した値、選択中のアイテム、APIから取得したデータなどが該当します。この動的なデータをコンポーネントが持つことで、データに変更があった際にReactは自動的に影響のあるコンポーネントを再レンダリングします。
フック(Hooks)とは
フック(Hooks)とは、関数コンポーネント内で状態管理などの処理を可能にするための仕組みです。フックはReact16.8で追加された機能で、関数コンポーネントに状態管理などの機能を追加するためのものです。従来はクラスコンポーネントでしか実装できなかったこれらの機能を、フックを使うことで関数コンポーネントでも扱えるようになりました。フックを使用することで、関数コンポーネントの機能の幅を広げ、シンプルで効率的な実装が可能になります。
状態管理とは
Reactにおける状態管理とは、コンポーネント内で動的なデータを一元管理し、そのデータの変更に応じてUIを効率的に更新することです。ユーザー操作による状態の変更を検出し、その影響がある部分を再レンダリングします。
WebサービスやECサイトでの状態管理の必要性
状態管理は、Webサービスを使用するユーザーのUX向上に必要な概念です。以下のように、サービスを提供する側は、状態管理を適切に行うことが求められます。
-
ユーザー操作による画面表示の変化
WebサービスやECサイトではユーザーがボタンを押したり、商品をカートに追加したりするなど、さまざまな操作により画面の表示内容が変わることが頻繁に起きます。Reactコンポーネントでアプリケーションを構築している場合、ユーザーの操作によって変更された状態をコンポーネントが記憶しておく必要があります。
-
状態管理の具体例とその重要性
例えば、ユーザーが欲しい商品をカートに追加し、他の商品を探すために別のページに遷移する場面を考えてみましょう。画面遷移によって表示内容が変更され、再レンダリングが行われる際にカートの中身がリセットされてしまうと、使いにくいサービスとなってしまいます。コンポーネントが変更された状態を記憶しておくことで、別の画面に遷移してもカートに追加された商品を保持することが可能になります。
useStateを使用する理由
JavaScriptの通常の変数で状態を管理する場合、その変数が何かデータを保持していたとしても、画面が再レンダリングされると保持していたデータは初期値に戻ってしまいます。再レンダリング前の変更されたデータを保持することはできません。useStateを使用することで、画面が再レンダリングされても、コンポーネント内のデータの状態を保持することが可能になります。
useStateの仕組み
ReactではuseStateを使うことにより、state(状態)を扱うことができます。useStateは以下の2つを提供します。
-
状態変数(state)
画面のレンダリング間でデータを保持する。
-
セッター関数(setter)
状態変数の値を更新し、再レンダリングをトリガーして新しい状態のコンポーネントを再表示する。
この2つを使用したuseStateの基本的な記述は以下のようになります。
// 状態変数の宣言 - 状態変数には現在の状態の値が入る
const [状態変数, セッター関数] = useState(状態変数の初期値);
// セッター関数に新しく渡す値を入力
セッター関数(新しい値)
例えば、カウントアップの例では以下のようになります。
// 状態変数の宣言 - 状態変数には現在の状態の値が入る
const [count, setCount] = useState(0);
// セッター関数に新しく渡す値を入力
setCount(5);
この記述例の内容を詳しく確認しましょう。
-
状態の宣言
状態を宣言するとは、コンポーネント内で管理される変数を定義し、その変数の値が変化したときにReactが自動的にコンポーネントを再レンダリングするように設定することです。記述例の状態の宣言は、
[count, setCount]
の部分です。状態の初期値を設定し、その状態変数と状態を変更するためのセッター関数を定義します。 -
状態変数の初期値
useStateは、初期状態として値を受け取ります。この初期値は、コンポーネントが最初にレンダリングされるときに設定されます。記述例では初期状態として
0
を受け取ります。この値は、コンポーネントが最初にレンダリングされるときのcount
の初期値になり、最初の画面に「0」が表示されます。初期値の記述例は他にも以下のようなものがあります。
const [text, setText] = useState('Hello'); // 初期値:'Hello'
const [lists, setLists] = useState([]); // 初期値:空の配列
-
状態の更新
状態を更新するためには、useStateから返されるセッター関数を使います。この関数に新しい状態の値を渡すことで、Reactはコンポーネントの再レンダリングをトリガーし、最新の状態を画面に表示します。記述例では
setCount(5)
と呼び出すと、count
の値が5
に更新され、コンポーネントが新しい値である「5」を使用して再レンダリングされます。
このように、useStateを使うことで、Reactの関数コンポーネント内で簡単に状態を管理し、レンダリング間の値の保持を可能にします。
useStateを使用したカウンターアプリの作成
では実際にuseStateを使用して、データの渡し方や状態の更新をハンズオンを通して体験しましょう。このハンズオンでは、以下のカウンターアプリを作成します。
ハンズオンを手軽に試したい方には、以下のサイトがおすすめです。Reactの環境構築が不要で、ブラウザ上でコードをすぐに試すことができます。
-
StackBlitz
-
StackBlitzについては、以下のサイトで詳しく解説しています。
ファイルの編集
このハンズオンでは以下の2つのファイルを使用して作成します。
- App.jsx
- App.css
-
App.jsxの編集
App.jsxを開き、以下のように編集します。
// App.jsx
import React, { useState } from 'react';
import './App.css';
function App() {
const [count, setCount] = useState(0);
return (
<div className="container">
<div className="counter">
<h2>Counter App</h2>
<p>{count}</p>
<div className="buttons-row">
<button onClick={() => setCount(count + 1)}>+</button>
<button onClick={() => setCount(count - 1)}>-</button>
</div>
<div className="button-reset">
<button onClick={() => setCount(0)}>reset</button>
</div>
</div>
</div>
);
}
export default App;
-
App.cssの編集
次にApp.cssを以下のように編集します。
/* App.css */
html,
body {
height: 100%;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
}
.container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
width: 100vw;
}
.counter {
background-color: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
text-align: center;
width: 240px;
}
h2 {
font-size: 1.8em;
margin-bottom: 20px;
}
p {
font-size: 3em;
margin-bottom: 40px;
}
.buttons-row {
display: flex;
gap: 10px;
margin-bottom: 20px;
justify-content: center;
}
.buttons-row button {
width: 80px;
background-color: #00bcd4;
color: white;
padding: 10px 0;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s;
}
.button-reset {
display: flex;
justify-content: center;
}
.button-reset button {
width: 170px;
background-color: #00bcd4;
color: white;
padding: 10px 0;
margin-bottom: 16px;
border: none;
border-radius: 5px;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover {
background-color: #0097a7;
}
button:focus {
outline: none;
}
ファイルの編集後、以下のようにカウンターアプリが表示できているかと思います。3つのボタンを押し、数字が変化するのを確認しましょう。
コードの説明
ハンズオンで使用したコードのuseStateに関連する部分を1つずつ確認していきます。
-
useStateのインポート
以下のようにuseStateをインポートすることで、関数コンポーネント内で状態管理ができるようになります。
import React, { useState } from 'react';
-
useStateの使用
ここでuseStateを呼び出し、状態変数とセッター関数、状態変数の初期値を宣言しています。今回の状態変数の初期値は「0」です。
const [count, setCount] = useState(0);
-
状態変数countの表示
JSX内で状態変数
count
を使うことで、現在のカウント値を表示します。count
の値が変わると、Reactは自動的にこの部分を再レンダリングし、最新の値を表示します。
<p>{count}</p>
-
セッター関数setCountの使用
それぞれのボタンは、
onClick
イベントを通じてセッター関数であるsetCount
関数を呼び出し、状態変数count
の値を更新します。状態が更新されると、Reactは自動的に再レンダリングを行い、最新の状態をUIに反映します
<button onClick={() => setCount(count + 1)}>+</button>
<button onClick={() => setCount(count - 1)}>-</button>
<button onClick={() => setCount(0)}>reset</button>
図に表すと以下の流れとなります。
このような一連の流れでユーザーが操作した状態を管理し、その最新の状態を画面に再表示します。useStateを使用することでレンダリング間の状態を保持し、ユーザーのUXを向上することが可能となります。
コンポーネントを分割しstateを共有する
最後に、コンポーネントを分割した際のstateの管理方法について学習しましょう。Reactでは複数のコンポーネントを組み合わせてUIを構築します。コンポーネントを分けることで、再利用性が高まり、実装の効率化を図ることができるため、コンポーネントは分割されるのが一般的です。
ボタンのコンポーネント化
今回はボタンをコンポーネント化します。Button.jsxファイルを作成し、以下のように編集します。
- Button.jsx
// Button.jsx
export default function Button({ onClick, label }) {
return <button onClick={onClick}>{label}</button>;
}
次に、App.jsxのボタンの記述を以下の通りに編集します。ボタンの値をラベル化し、それぞれのボタンに適用します。ボタンラベルの内容に基づいて条件分岐し、ラベルに合わせた値をセッター関数に渡します。
// App.jsx
import React, { useState } from 'react';
import Button from './Button';
import './App.css';
function App() {
const [count, setCount] = useState(0);
// ボタンラベルの内容で条件分岐し、ラベルに合わせた値をセッター関数に渡す
const handleButtonClick = (label) => {
if (label === '+') {
setCount(count + 1);
} else if (label === '-') {
setCount(count - 1);
} else if (label === 'reset') {
setCount(0);
}
};
return (
<div className="container">
<div className="counter">
<h2>Counter App</h2>
<p>{count}</p>
<div className="buttons-row">
{['+', '-'].map((label) => (
<Button
key={label}
label={label}
onClick={() => handleButtonClick(label)}
/>
))}
</div>
<div className="button-reset">
<Button
label="reset"
onClick={() => handleButtonClick('reset')}
/>
</div>
</div>
</div>
);
}
export default App;
コードの修正結果は、見た目の変化はありませんが、コンポーネントの分割をすることができました。
コンポーネント間での状態の共有
ボタンをコンポーネント化したことで、状態がコンポーネント間でどのように共有されているか確認していきましょう。
Button.jsxでは、親コンポーネントであるApp.jsxからprops
としてlabel
とonClick
のプロパティを受け取ります。これにより、Appコンポーネントの状態とロジックをButtonコンポーネントに渡すことができます。
// Button.jsx
// Appコンポーネントから「onClick, label」のプロパティを受け取る
export default function Button({ onClick, label }) {
return <button onClick={onClick}>{label}</button>;
}
受け取ったラベルの内容に基づいて、AppコンポーネントのhandleButtonClick
関数をButtonコンポーネント内から呼びだし、操作することが可能となります。
図に表すと以下の流れとなります。
コンポーネント間で状態を共有しながら、コンポーネントの再利用性を高めることが可能になりました。今回紹介したこの方法は、Reactの基本的な状態管理のパターンの1つです。useStateでの状態管理は、親コンポーネントが状態を管理し、子コンポーネントがその状態を操作するための関数を受け取る形で実現されます。
この記事で学んだこと
ここまでuseStateについて、その基本と実際の使い方を学びました。簡単に振り返ってみましょう。
-
useStateとは
useStateとは、Reactの関数コンポーネントの中で状態を管理するためのReact Hooksの1つです。コンポーネントが状態を持つことで、ユーザーが操作したデータの変更に即座に反応し、画面の表示内容を動的に変化させることが可能になります。
-
useStateを使用する理由
useStateを使用することで、画面の再レンダリング間でデータの状態を保持することができます。これにより、画面遷移が行われる中でも、追加したカートの中身や他のさまざまなユーザー操作の状態を保持できるため、WebサービスのUX向上に欠かせない仕組みとなります。
参考資料
以下のリンクは、この記事で説明した手順や概念に関連する参考資料です。より詳しく学びたい方は、ぜひご参照ください。
【番外編】USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話
プログラミング塾に半年通えば、一人前になれると思っているあなた。それ、勘違いですよ。「なぜ間違いなの?」「正しい勉強法とは何なの?」ITを学び始める全ての人に知って欲しい。そう思って書きました。是非読んでみてください。
「フリーランスエンジニア」
近年やっと世間に浸透した言葉だ。ひと昔まえ、終身雇用は当たり前で、大企業に就職することは一種のステータスだった。しかし、そんな時代も終わり「優秀な人材は転職する」ことが当たり前の時代となる。フリーランスエンジニアに高価値が付く現在、ネットを見ると「未経験でも年収400万以上」などと書いてある。これに釣られて、多くの人がフリーランスになろうとITの世界に入ってきている。私もその中の1人だ。数年前、USBも知らない状態からITの世界に没入し、そこから約2年間、毎日勉学を行なった。他人の何十倍も努力した。そして、企業研修やIT塾で数多くの受講生の指導経験も得た。そこで私は、伸びるエンジニアとそうでないエンジニアをたくさん見てきた。そして、稼げるエンジニア、稼げないエンジニアを見てきた。
「成功する人とそうでない人の違いは何か?」
私が出した答えは、「量産型エンジニアか否か」である。今のエンジニア市場には、量産型エンジニアが溢れている!!ここでの量産型エンジニアの定義は以下の通りである。
比較的簡単に学習可能なWebフレームワーク(WordPress, Rails)やPython等の知識はあるが、ITの基本概念を理解していないため、単調な作業しかこなすことができないエンジニアのこと。
多くの人がフリーランスエンジニアを目指す時代に中途半端な知識や技術力でこの世界に飛び込むと返って過酷な労働条件で働くことになる。そこで、エンジニアを目指すあなたがどう学習していくべきかを私の経験を交えて書こうと思った。続きはこちらから、、、、
エンベーダー編集部
エンベーダーは、ITスクールRareTECHのインフラ学習教材として誕生しました。 「遊びながらインフラエンジニアへ」をコンセプトに、インフラへの学習ハードルを下げるツールとして運営されています。
関連記事
2020.02.25
完全未経験からエンジニアを目指す爆速勉強法
USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話
- キャリア・学習法
- エンジニア
2024.09.22
そもそも開発におけるフロントエンドの役割は?
本記事では、フロントエンドに興味を持つ初心者の方々に向けて、フロントエンドの基本概念やその重要性についてわかりやすく解説します。
- フロントエンド
2024.10.28
Reactの基本、useCallbackを理解しよう
useCallbackは、関数をメモ化し、再レンダリング時に不必要な関数の再作成を避けることができる仕組みです。
- React
- フロントエンド
2024.01.30
【初心者向け】Next.jsで高速でSEOに強いWebアプリケーションを構築
この記事では、近年、モダンフロントエンド開発において最も人気の高いVercel社が提供しているオープンソースのWebアプリケーションフレームである、「Next.js」について解説します。
- フロントエンド