はじめに
こんにちは!
ガク@Necono_Engineerと申します!
プログラミングスクールRUNTEQで現在Ruby on Railsを中心に学んでいます。今回はポートフォリオ作成のためにReact
を学んでいる過程で出会ったuseState
とuseEffect
についてまとめてみました!
プログラミング初学者のため、内容に誤りがある可能性がございます。
もし間違いがあればご指摘いただけると幸いです。
React Hooks
今回学んだuseState
とuseEffect
はReact Hooksの1つです。
React Hooksとは?
2017年の9月にリリースされたReact16.8からの機能です。
以前は、クラスコンポーネントでしか扱えなかった、Stateやライフサイクルの機能をHooks
を使用することで関数コンポーネントに取り付ける(Hook up)ことができます。
useState
特に頻繁に使用されるフックとしてuseState
があります。
useState
を使用することで関数コンポーネント内でstate(状態)
を保持することができるようになります。
使用方法
import { useState } from 'react';
トップレベルでuseStateをインポートすることで使用可能になります。
- 状態(
state
)とその状態を更新する関数(setState
)を定義します。 - 初期値を設定します。
const [state, setState] = useState(false);
記述名 | 備考 |
---|---|
state | 現在の値 |
setState | stateの状態を変更する関数 |
false | 初期値 |
Stateとは?
Reactのコンポーネントは内部で「状態」を持つことができます。
状態
状態はアプリケーションやコンポーネントの現在の情報のことで、state
と呼ばれます。
Stateの流れ
- コンポーネントの状態を保存
- その状態が変更された時に自動的にコンポーネントを更新(再レンダリング)
例) クリックすると数字が+1されるCounterコンポーネント
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Current Count: {count}</p>
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
);
}
export default Counter;
↑ コンポーネントが内部で保持するstate
が更新されると、コンポーネントが再描画され画面上のUIが変化します。
上記のコードでは更新関数であるsetCountを呼び出すと状態が変化します。
<button onClick={() => setCount(count + 1)}>+1</button>
ボタンに onClick イベントハンドラーを追加し、クリックすると setCount 関数を呼び出して count の値を1増やすように設定しています。
更新関数(setのついたもの)は現在の count 値に 1 を加えた値で count を更新します。
setCount(count + 1)
そして、
<p>Current Count: {count}</p>
この{count}の部分で現在のcountの値をJavaScript変数として表示しています。(JSX構文内ではJavaScriptの式を使用でき、{ }で表現されます。)
このようにuseState
を使用することでコンポーネント内で動的な処理が可能になります!
useEffect
useEffect
は、React コンポーネント内で副作用を実行するために使用されるフックです。
副作用
UIのレンダリングに直接関係しない操作を指します。
これには以下のようなものが含まれます
- API からデータを取得する
- タイマーをセットする
- DOM ノードを直接操作する など。
依存配列
useEffect には、第2引数として「依存配列」を渡すことができます。
useEffect(() => {
// 副作用を実行する処理を記述する
}, [依存配列]);
記述名 | 備考 |
---|---|
副作用 | 第1引数 |
依存配列 | 第2引数 |
- 依存配列が指定されている場合
配列内の値が変更されたときにのみ、副作用が再実行されます。
以下のコードでは(userId)が変化したときに、APIからユーザーのデータを取得するという副作用の処理を行います。
import React, { useState, useEffect } from 'react'; //useEffectの定義
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
async function fetchUserData() {
const response = await fetch(`https://api.example.com/users/${userId}`);
const userData = await response.json();
setUser(userData);
}
fetchUserData();
}, [userId]); // userIdが変更されたときのみこの副作用を実行
return (
<div>
{/* ユーザーデータの表示 */}
{user && <div>{user.name}</div>}
</div>
);
}
export default UserProfile
- 依存配列が空の場合([])
useEffectはコンポーネントがマウントされた後に一度だけ実行されます。
その後、propsやstateの変更があってUIが再描画された場合(再レンダリング)でも副作用は再実行されません。
マウント
コンポーネントに対するDOMノードを作成、既存のDOMツリーに挿入し、webページ上にコンポーネントが初めて描画された時のことを言います。アンマウントはDOMノードが既存のDOMツリーから削除された時のことを言います。
以下のコードではコンポーネントがマウントされた時にタイマーをセットし、アンマウントされた時にクリアします。
import React, { useState, useEffect } from 'react';
function TimerComponent() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const intervalId = setInterval(() => {
setSeconds(prevSeconds => prevSeconds + 1);
}, 1000);
return () => clearInterval(intervalId); // コンポーネントのアンマウント時にインターバルをクリア
}, []); // 依存配列が空なので、マウント時にのみ実行される
return <div>経過秒数: {seconds}</div>;
}
export default TimerComponent
- 依存配列が指定されていない場合:
副作用はコンポーネントの初回マウント時と、その後のすべての更新(再レンダリング)後に実行されます。stateやpropsのどの変更にも反応して副作用を実行します。
stateやpropsの更新 → UIの再描画 → 処理の実行の順番で行われ、コンポーネントが画面に表示されたときや更新されたときに特定のコードを実行することができます。
まとめ
useStateとuseEffectを調べていくにつれてからReactの基礎概念である状態、副作用、マウントなどについても少しだけですが知ることができました。実践でフックを適切に扱えるよう今後も学習を進め、Reactへの理解をさらに深めたいと思います!
参考文献
書籍
- 基礎から学ぶReact Hooks
- Reactハンズオンラーニング 第2版 ―Webアプリケーション開発のベストプラクティス
- TypeScriptとReact/Next.jsでつくる実践Webアプリケーション開発
記事