Reactは、ユーザーインターフェースを構築するためのJavaScriptライブラリです。その中核をなす概念の一つが「状態(state)」です。
useStateとuseEffectは、Reactのフックと呼ばれる機能で、状態管理と副作用の管理を行います。
useStateがない場合
function App() {
let count = 0;
const handleClick = () => {
count++;
console.log(count);
};
return (
<>
<h1>普通のカウント</h1>
<button onClick={handleClick}>Click Me!</button>
<p>{count}</p>
</>
);
}
上記のコードでは、count
はただの変数です。
ボタンをクリックするとcount
の値は増加しますが、これはReactのレンダリングシステムとは独立しています。そのため、画面上のカウントは更新されず、常に0が表示されます。
useStateを使う場合
import { useState } from "react";
function App() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
};
return (
<>
<h1>UseState</h1>
<button onClick={handleClick}>Click Me!</button>
<p>{count}</p>
</>
);
}
useStateを使うと、count
は状態として管理され、setCount
関数によって更新されます。これにより、状態が変更されるとReactはコンポーネントを再レンダリングし、画面上のカウントが実際の値に更新されます。
useEffectの使い方
useEffectは、コンポーネントのライフサイクルに応じた副作用(データの取得、購読の設定など)を扱います。
マウント時に一度だけ実行
import { useEffect } from "react";
function App() {
useEffect(() => {
console.log("マウント時に一度だけ実行");
}, []);
return (
<>
<h1>UseEffect:デフォルト(マウント時に一度だけ実行)</h1>
</>
);
}
上記のコードでは、空の依存配列([]
)を渡すことで、コンポーネントがマウントされた時に一度だけ副作用が実行されます。
依存配列の変数が変わった時に発火
import { useEffect, useState } from "react";
function App() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
};
useEffect(() => {
console.log("countが変更されました");
}, [count]);
return (
<>
<h1>UseEffect:変数が変更された時に実行</h1>
<button onClick={handleClick}>+1</button>
<p>count: {count}</p>
</>
);
}
ここでは、count
が更新されるたびに副作用が実行されます。これは、count
を依存配列に含めることで実現されます。
無限ループの危険性
import { useEffect, useState } from "react";
function App() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log("NG:countが永遠に変更されるので、無限ループになる");
setCount(count + 1);
}, [count]);
return (
<>
<h1>UseEffect:無限ループ</h1>
<button onClick={handleClick}>+1</button>
<p>count: {count}</p>
</>
);
}
上記のコードは、count
が更新されるたびにsetCount
を呼び出しているため、無限ループに陥ります。これは避けるべきです。
おわり
以上がuseStateとuseEffectの基本的な使い方と、それらを使ってReactでの状態管理と副作用を扱う方法です。
これらのフックを適切に使うことで、効率的で再利用可能なコンポーネントを作成することができます。