こんにちは!
useState
って聞いたことありますか?
今回は、Reactの重要な機能である「useState
」について詳しく解説します。
useState
は、Reactで状態を管理するための強力なツールなんです。
でも「状態って何?」って思いましたか?
簡単に言えば、アプリの中で変化するデータのことです。
例えば、ボタンを押すたびに増える数字とか、ユーザーが入力したテキストとか。
そういったものを簡単に扱えるようにしてくれるのが、このuseState
なんです。
useState
の基本的な概念と使い方- 数値、文字列、真偽値など様々なデータ型での使用方法
useState
を使う際の注意点- 実際のアプリケーションでの活用例
React環境がない方はこちらも参考にしてください。
useStateフックとは?
まずは、useState
フックの基本的な概念について説明しましょう。
useState
は、Reactの「フック」と呼ばれる機能の一つです。
フックとは、関数型コンポーネントで状態や他のReactの機能を使えるようにする特別な関数のこと。
その中でもuseState
は、コンポーネントに状態を追加するために使われます。
状態って何?と思う方もいるかもしれません。
簡単に言えば、アプリケーションの中で変化する可能性のあるデータのことです。
例えば、ユーザーの入力、APIからのデータ、時間の経過によって変わる値などが該当します。
useState
を使うと、この状態を簡単に管理できるんです。
値の更新と、その更新に伴う画面の再描画を自動的に行ってくれるので、開発者はロジックに集中できます。
以前のReactでは、クラスコンポーネントを使って状態を管理していました。
でも、useState
を含むフックの導入により、関数型コンポーネントでも簡単に状態管理ができるようになりました。
コードがシンプルになり、理解しやすくなったんです。
useState
は非常に柔軟で、数値、文字列、真偽値、オブジェクト、配列など、様々な型のデータを扱えます。
useStateの基本的な使い方
useState
の基本的な使い方を、5つの異なるデータ型を例に解説します。
それぞれのケースで、どのようにuseState
を使うのか、実際のコード例を交えて説明していきますね。
1. 数値の状態管理
まずは、最もシンプルな例として数値の状態管理を見てみましょう。
カウンターアプリを想像してください。
ボタンをクリックするたびに数字が増えていく、あのシンプルなアプリです。
このカウンターの数値を管理するのに、useState
が使えます。
import React, { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState<number>(0);
const increment = () => {
setCount(count + 1);
};
return (
<div>
<p>カウント: {count}</p>
<button onClick={increment}>増やす</button>
</div>
);
};
このコードでは、useState(0)
で初期値0の状態を作成しています。
count
が現在の値、setCount
が値を更新する関数です。
ボタンをクリックするとincrement
関数が呼び出され、setCount
で値が更新されます。
2. 文字列の状態管理
次は、文字列の状態管理です。
例えば、ユーザーの入力を管理する場合によく使われます。
入力フォームの値を状態として保持し、更新する例を見てみましょう。
import React, { useState } from 'react';
const InputForm = () => {
const [name, setName] = useState<string>('');
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setName(event.target.value);
};
return (
<div>
<input type="text" value={name} onChange={handleChange} />
<p>こんにちは、{name}さん!</p>
</div>
);
};
ここでは、
で空の文字列を初期値として状態を作成しています。useState
('')
入力フォームの値が変更されるたびにhandleChange
関数が呼び出され、setName
で状態が更新されます。
3. 真偽値の状態管理
真偽値(ブール値)の状態管理も、useState
でよく行われます。
例えば、何かの表示・非表示を切り替えるトグルスイッチなどに使えます。
import React, { useState } from 'react';
const ToggleSwitch = () => {
const [isOn, setIsOn] = useState<boolean>(false);
const toggle = () => {
setIsOn(!isOn);
};
return (
<div>
<button onClick={toggle}>{isOn ? 'ON' : 'OFF'}</button>
<p>{isOn ? '電気がついています' : '電気が消えています'}</p>
</div>
);
};
この例では、
で初期値がfalseの状態を作成しています。useState
(false)
ボタンをクリックするたびにtoggle
関数が呼び出され、setIsOn
で状態が反転します。
4. オブジェクトの状態管理
より複雑なデータ構造、例えばオブジェクトの状態管理もuseState
で行えます。
ユーザー情報のような複数のプロパティを持つデータを管理する場合に便利です。
import React, { useState } from 'react';
interface UserInfo {
name: string;
age: number;
}
const UserProfile = () => {
const [user, setUser] = useState<UserInfo>({ name: '', age: 0 });
const handleNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setUser({ ...user, name: event.target.value });
};
const handleAgeChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setUser({ ...user, age: Number(event.target.value) });
};
return (
<div>
<input type="text" value={user.name} onChange={handleNameChange} placeholder="名前" />
<input type="number" value={user.age} onChange={handleAgeChange} placeholder="年齢" />
<p>名前: {user.name}, 年齢: {user.age}</p>
</div>
);
};
この例では、名前と年齢を持つオブジェクトを状態として管理しています。
状態を更新する際は、setUser
で新しいオブジェクトを作成して更新します。
オブジェクトの一部のプロパティだけを更新する場合は、スプレッド構文(...user
)を使って他のプロパティを保持しつつ、特定のプロパティを更新しています。
5. 配列の状態管理
最後に、配列の状態管理を見てみましょう。
TODOリストのような、複数のアイテムを管理する場合によく使われます。
import React, { useState } from 'react';
const TodoList = () => {
const [todos, setTodos] = useState<string[]>([]);
const [newTodo, setNewTodo] = useState<string>('');
const addTodo = () => {
if (newTodo.trim() !== '') {
setTodos([...todos, newTodo]);
setNewTodo('');
}
};
return (
<div>
<input
type="text"
value={newTodo}
onChange={(e) => setNewTodo(e.target.value)}
placeholder="新しいTODOを入力"
/>
<button onClick={addTodo}>追加</button>
<ul>
{todos.map((todo, index) => (
<li key={index}>{todo}</li>
))}
</ul>
</div>
);
};
この例では、TODOアイテムの配列を
で管理しています。useState
新しいTODOを追加する際は、setTodos
で既存の配列に新しい要素を追加した新しい配列を作成しています。
useStateで複数の状態を管理するには
複数の状態を管理する方法はいくつかあります。
状況に応じて適切な方法を選びましょう。
複数のuseStateを使う
関連性の薄い複数の状態がある場合、それぞれに対してuseState
を使うのが簡単です。
const [name, setName] = useState<string>('');
const [age, setAge] = useState<number>(0);
const [isStudent, setIsStudent] = useState<boolean>(false);
オブジェクトとして管理
関連する複数の状態がある場合、一つのオブジェクトとして管理するのが便利です。
const [user, setUser] = useState<{ name: string; age: number; isStudent: boolean }>({
name: '',
age: 0,
isStudent: false
});
更新時は、スプレッド構文を使って一部のプロパティだけを更新できます:
setUser(prevUser => ({ ...prevUser, name: 'Alice' }));
useReducerを使う
状態の更新ロジックが複雑な場合、useReducer
フックを使うのも一つの選択肢です。
これについては、別途学習するのがおすすめですよ。
状態管理の方法は、アプリケーションの規模や複雑さによって変わってきます。
小規模なアプリケーションなら複数のuseState
で十分ですが、大規模になってくるとuseReducer
やRedux
などの状態管理ライブラリの使用を検討する必要があるかもしれません。
useStateと普通の変数の違いは?
useState
で管理される状態と普通の変数の主な違いは、状態が変更されたときの挙動です。
useState
で管理される状態が変更されると、Reactはそのコンポーネントを自動的に再描画します。
つまり、画面上の表示が新しい状態を反映して更新されるんです。
一方、普通の変数を変更しても、Reactはその変更を検知できません。
そのため、画面の更新は行われません。
例えば、カウンターアプリで普通の変数を使うと、こんな感じになります:
let count = 0;
const increment = () => {
count += 1;
console.log(count); // 値は増えていますが、画面には反映されません
};
この場合、count
の値は増えていきますが、画面上には反映されません。
useState
を使うことで、状態の変更と画面の更新を連動させられるんです。
useStateを使う際の注意点
useState
は便利な機能ですが、使う際にはいくつか注意点があります。
ここでは、主に2つの重要なポイントについて解説します。
状態更新の非同期性
まず知っておくべきなのは、useState
による状態の更新は非同期的だということです。
これはどういうことでしょうか?
簡単に言えば、状態を更新する関数(setCount
など)を呼び出した直後に、その新しい値を使おうとしても、まだ更新が反映されていない可能性があるということです。
例えば、以下のようなコードは期待通りに動作しないかもしれません:
const [count, setCount] = useState<number>(0);
const incrementAndLog = () => {
setCount(count + 1);
console.log(count); // この値は更新前の値かもしれません
};
このincrementAndLog
関数では、setCount
で値を更新した直後にconsole.log
でcount
の値を出力していますが、この時点ではcount
の値がまだ更新されていない可能性があります。
前の状態を基に更新する方法
このような問題を解決する方法の一つが、更新関数に関数を渡す方法です。
これを使うと、前の状態を確実に取得して、それを基に新しい状態を計算できます。
const [count, setCount] = useState<number>(0);
const incrementAndLog = () => {
setCount(prevCount => {
const newCount = prevCount + 1;
console.log(newCount); // この値は確実に更新後の値です
return newCount;
});
};
この方法を使えば、確実に最新の状態を基に更新できます。
特に、複数の更新を連続して行う場合や、現在の状態に依存して更新を行う場合に有効です。
また、オブジェクトや配列の状態を更新する際は、直接変更するのではなく、新しいオブジェクトや配列を作成して更新することが重要です。
これは、Reactが状態の変更を検知しやすくなり、不要な再描画を防ぐためです。
// オブジェクトの更新(正しい方法)
setUser(prevUser => ({ ...prevUser, name: 'Alice' }));
// 配列の更新(正しい方法)
setTodos(prevTodos => [...prevTodos, newTodo]);
これらの点に注意しながらuseState
を使うことで、より予測可能で効率的なReactアプリケーションが作れるようになります。
useStateの実践的な使用例
ここまでuseState
の基本的な使い方と注意点を学んできました。
では、実際のアプリケーションではどのように使われるのでしょうか?
ここでは、2つの実践的な例を通じて、useState
の活用方法を見ていきましょう。
シンプルなカウンターアプリ
まずは、シンプルなカウンターアプリを作ってみます。
このアプリでは、ボタンをクリックすると数字が増減するという基本的な機能を実装します。
import React, { useState } from 'react';
const Counter = () => {
const [count, setCount] = useState<number>(0);
const increment = () => {
setCount(prevCount => prevCount + 1);
};
const decrement = () => {
setCount(prevCount => prevCount - 1);
};
return (
<div>
<h2>カウンター</h2>
<p>現在の数: {count}</p>
<button onClick={increment}>増やす</button>
<button onClick={decrement}>減らす</button>
</div>
);
};
export default Counter;
このカウンターアプリでは、
を使ってuseState
count
という状態を管理しています。
increment
関数とdecrement
関数で状態を更新し、その値を画面に表示しています。
注目すべき点は、状態を更新する際に前の状態を基に計算している点です。
これにより、複数の更新が連続して行われても正確に状態を管理できます。
TODOリストの作成
次に、もう少し複雑な例として、TODOリストを作ってみましょう。
このアプリでは、新しいTODOの追加、完了したTODOの削除、そして残りのTODO数の表示といった機能を実装します。
import React, { useState } from 'react';
interface Todo {
id: number;
text: string;
}
const TodoList = () => {
const [todos, setTodos] = useState<Todo[]>([]);
const [inputText, setInputText] = useState<string>('');
const addTodo = () => {
if (inputText.trim() !== '') {
setTodos(prevTodos => [...prevTodos, { id: Date.now(), text: inputText }]);
setInputText('');
}
};
const deleteTodo = (id: number) => {
setTodos(prevTodos => prevTodos.filter(todo => todo.id !== id));
};
return (
<div>
<h2>TODOリスト</h2>
<input
type="text"
value={inputText}
onChange={(e) => setInputText(e.target.value)}
placeholder="新しいTODOを入力"
/>
<button onClick={addTodo}>追加</button>
<ul>
{todos.map(todo => (
<li key={todo.id}>
{todo.text}
<button onClick={() => deleteTodo(todo.id)}>完了</button>
</li>
))}
</ul>
<p>残りのTODO: {todos.length}個</p>
</div>
);
};
export default TodoList;
この例では、2つの状態を管理しています。
todos
はTODOリストの配列、inputText
は新しいTODOを入力するためのテキストです。
addTodo
関数では、入力されたテキストを基に新しいTODOオブジェクトを作成し、既存のTODO配列に追加しています。
ここでも、前の状態を基に新しい配列を作成していますね。
deleteTodo
関数では、指定されたIDのTODOを配列から削除しています。
filter
メソッドを使って新しい配列を作成することで、元の配列を直接変更することを避けています。
また、残りのTODO数を表示する部分では、todos.length
を使って簡単に計算しています。
これはtodos
の状態が変わるたびに自動的に更新されます。
これらの例を通じて、useState
がどのように実際のアプリケーションで使われるのかがわかったのではないでしょうか。
シンプルな状態管理から、より複雑なデータ構造の管理まで、useState
は幅広く活用できます。
ひとつひとつ真摯に向き合う企業
株式会社 ONE WEDGEでは、新たな仲間を募集しています!
私たちと一緒に、革新的で充実したキャリアを築きませんか?
当社は、従業員が仕事と私生活のバランスを大切にできるよう、充実した福利厚生を整えています。
- 完全週休2日制(土日休み)で、祝日や夏季休暇、年末年始休暇もしっかり保証!
- 様々な休暇制度(有給、慶弔、産前・産後、育児、バースデー休暇)を完備!
- 従業員の成長と健康を支援するための表彰制度、資格取得支援、健康促進手当など!
- 生活を支えるテレワーク手当、記事寄稿手当、結婚祝金・出産祝金など、様々な手当を提供!
- 自己啓発としての書籍購入制度や、メンバー間のコミュニケーションを深める交流費補助!
- 成果に応じた決算賞与や、リファラル採用手当、AI手当など、頑張りをしっかり評価!
- ワークライフバランスを重視し、副業もOK!
株式会社 ONE WEDGEでは、一人ひとりの従業員が自己実現できる環境を大切にしています。
共に成長し、刺激を与え合える仲間をお待ちしております。
あなたの能力と熱意を、ぜひ当社で発揮してください。
ご応募お待ちしております!
ホームページ、採用情報は下記ボタンからご確認ください!
応募、ご質問など、LINEでお気軽にご相談ください♪
まとめ
ここまで、ReactのuseState
フックについて詳しく見てきました。
改めて、重要なポイントを振り返ってみましょう。
useState
は、関数コンポーネントで状態を管理するためのフックです。- 様々なデータ型(数値、文字列、真偽値、オブジェクト、配列など)で使用できます。
const [state, setState] =
の形で使います。useState
(initialValue)state
が現在の状態、setState
が状態を更新する関数です。- 状態の更新は非同期的に行われます。
更新直後に新しい値を使用したい場合は注意が必要です。 - 前の状態を基に更新する場合は、更新関数に関数を渡すのが安全です。
例:setCount(prevCount => prevCount + 1)
- オブジェクトや配列の状態を更新する際は、新しいオブジェクトや配列を作成して更新します。
useState
を使うことで、動的で対話的なユーザーインターフェースを簡単に作成できます。
useState
は、Reactアプリケーション開発の基本的なツールの一つです。
これをマスターすることで、より複雑な状態管理や他のReactフックの理解へとステップアップできます。
次のステップとしては、useEffect
フックを学ぶのがおすすめです。
useEffect
を使うことで、副作用(サイドエフェクト)の管理ができるようになり、より高度なアプリケーションの開発が可能になります。
また、状態管理がより複雑になってきたら、useReducer
フックやRedux
のような状態管理ライブラリの使用も検討してみてください。