🔰
【React hooks】useStateの使い方あれこれ
この記事の内容
- コンポーネント内で状態を管理するために使用しているuseStateの使い方をまとめました。
- 個人的なポイントも一緒に書いていきます。
- この記事のサンプルコードはTypeScriptを使っています。
- 必要なところだけサクッと読みたい人へ
useStateとは
- 関数コンポーネントでstateを管理(stateの保持や更新)するためのReactフック。
- stateとは、コンポーネントが内部で保持する状態のことで、主に画面上に表示する項目、入力値などに使用しています。
ボタンを押して値を更新する
- カウントアップボタンが押されるたびに、
Count:{count}
の値が増えていきます。
const [count, setCount] = useState<number>(0);
const handleClick = () => {
setCount(count + 1)
}
return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>カウントアップ</button>
</div>
)
count
の値が更新されるタイミングは再レンダリングの後
【ポイント!】- 状態の更新は非同期で行われます。
そのため、setCount
が呼び出された後、即座にcount
の値が更新されるわけではないんです。
Next.js(React)が状態の変更を検出し、コンポーネントが再レンダリングされたタイミングでcount
の値が更新されます。 - 流れはこう。
-
- ボタン押す
-
-
handleClick
関数が呼び出される
-
-
-
setCount
が呼び出されて、count
の値が更新される
-
-
- コンポーネントが再レンダリングされ、最新の
count
の値が表示される
- コンポーネントが再レンダリングされ、最新の
-
親コンポーネントから子コンポーネントに関数を渡す
- 子コンポーネントで状態を更新したい場合は、stateのset関数をpropとして子コンポーネントに渡すことができます。
- さっきのstateを、親コンポーネントから子コンポーネントに渡してみましょう。
- これで、子コンポーネントでの状態の更新を親コンポーネントに反映できます。
親コンポーネント.tsx
const ParentComponent: React.FC = () => {
const [count, setCount] = useState<number>(0);
return (
<div>
<ChildComponent setCount={setCount} />
<p>Count: {count}</p>
</div>
)
}
子コンポーネント.tsx
// 型の定義
interface ChildProps {
// `React.SetStateAction<T>`は、useStateの型(ジェネリック型)
// <>の中にstateの型を指定する
setCount: React.Dispatch<React.SetStateAction<number>>;
}
// ↓ 引数にsetCountを渡す
const ChildComponent: React.FC<ChildProps> = ({ setCount }) => {
const handleIncrement = () => {
// カウントアップ処理
setCount((prevCount) => prevCount + 1)
}
return (
<button onClick={handleIncrement}>子コンポーネントでカウントアップ</button>
)
}
useStateの型にオブジェクト型を指定
- useStateの型は、stringやnumberだけではなく、オブジェクト型も指定できます
- オブジェクト型にして、入力フォームの情報をまとめて指定できます
// 入力フォーム情報
interface FormState {
name: string
age: number
email: string
}
const MyComponent: React.FC = () => {
// ↓ 入力フォームの型を指定
const [formData, setFormData] = useState<FormState>({
// 初期値を指定
name: '',
age: 0,
email: '',
});
オブジェクト型の値を更新する
- ボタンを押したタイミングで値を更新してみる。
- 例えばこんな感じで。・・・あれ?更新されない。。。
const clickChange = () => {
formData.name = 'PONCHAN'
setFormData(formData)
}
- 参照先が変わっておらず、中身のデータが直接変わっている状態だとsetしても変わらないらしい。。
【ポイント!】更新する場合はスプレッド構文を使おう
-
setFormData
などのset関数は、新しい状態に更新する場合、前の状態を変更せずに新しい状態を返す必要があります。 - オブジェクトは参照型なので、前の状態を変更せずに新しいオブジェクトを作成する。
- 直接変更すると同じ参照を持つ他の箇所にも影響を及ぼす可能性も。。。
スプレッド構文(...)を使用して新しいオブジェクトを作成しよう!
const clickChange = () => {
const updatedFormData = {
...formData,
name: 'YUMI'
}
setFormData(updatedFormData);
}
- onChangeを使って、入力値が変わったものだけを更新もできる!
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
// 変更された入力値
const { name, value } = e.target
// 入力フォーム情報にセットする
setFormData((prevFormData) => ({
...prevFormData,
[name]: value,
}))
}
return (
<div>
<input
type="text"
name="name"
value={formData.name}
onChange={handleChange}
/>
以上、普段使っているuseStateの使い方まとめでした!
Discussion