
はじめに
Reactの状態管理ライブラリといえば、Reduxが有名ですが、その学習コストの高さから初心者にとっては難しいと感じられることがあります。しかし、Reactでの開発において「状態管理」を理解することはとても重要です。多くの開発現場で状態管理ライブラリが使用されているため、早い段階で触れておくと良いでしょう。
そこで今回ご紹介するのが Jotai です。Jotaiはそのシンプルさと使いやすさで人気のライブラリで、特に初心者におすすめです。Reactの useState のような感覚で状態を管理できるため、Reduxより学習コストが低く、すぐに使いはじめることができます。
この記事では、Jotaiと状態管理についてわかりやすく解説します。この記事を読み終える頃には、Jotaiを使った状態管理の基本が理解できるようになることを目指しています。React初心者の方が、状態管理ライブラリを導入する際の第一歩となれば幸いです。それでは、一緒に学んでいきましょう。
この記事について
この記事のゴール
- Jotaiの基本的な使い方を理解し、簡単なアプリに実装できるようになること
記事の対象者
- Reactを学び始めたばかりの初心者
- 状態管理の仕組みやJotaiの使い方を知りたい方
Jotaiとは?
Jotaiは、Reactで使える状態管理ライブラリの一つで、近年注目を集めています。その名前は、日本語の「状態」から由来しています。
Jotaiを使えば、Reactの状態を useState のようにシンプルで直感的に扱うことができます。そのため、初心者の方でもすぐに導入でき、使いやすいのが特徴です。
Jotaiはアプリ内で使うデータ(状態)を「atom(アトム)」という小さな単位で管理します。それぞれのatomは必要な場所だけで使えるため、不要な再レンダリングを防ぎ、コードをシンプルに保つことが可能です。
Jotaiが注目されている理由
Jotai は、 JavaScript Risingstars 2024 のランキングで2位にランクインしました。JavaScript Rising Stars は、JavaScript ライブラリのトレンドを発表しています。このランキングは、1年間で増えた GitHub スターの数をもとにしており、注目されている技術を知ることができます。この結果から、Jotai は注目されている状態管理ライブラリということがわかります。
出典:JavaScript Rising Stars
https://risingstars.js.org/2024/en
また、Jotaiは npm trends でもその利用状況を確認できます。他の状態管理ライブラリと比べてダウンロード数は少ないものの、ユーザーによる継続的な利用が見られます。さらに、開発は現在も活発に行われており、定期的なアップデートも提供されています。
出典:npm trends
https://npmtrends.com/jotai-vs-recoil-vs-redux-vs-xstate-vs-zustand
2025年1月に Recoil の開発が停止したことを受け、その仕組みに似た Jotai が代替案として注目されています。これらの点から、今後が期待される状態管理ライブラリといえるのではないでしょうか。
状態管理ライブラリとは
次に、状態管理ライブラリ について簡単に触れておきましょう。状態管理ライブラリとは、アプリ内で使われる「データ(状態)」を効率的かつ一元的に管理するためのツールです。
状態とはアプリの「現在の状況」を表すもの
「状態(state)」とは、アプリが「今どういう状況にあるか」を示すデータのことを指します。具体的には、以下のようなデータが状態として管理されます。
- ユーザーのログイン状態
- ショッピングカートに入っている商品
- フォームに入力されたテキスト
これらは、ユーザーがアプリを使う中で頻繁に変化します。状態を適切に管理することで、アプリの動作がスムーズになり、ユーザー体験の向上につながります。
状態管理ライブラリが必要な理由
Reactには useState や useReducer といった状態管理の仕組みが用意されています。しかし、アプリが大規模になるにつれて、以下のような問題が発生することがあります。
-
状態の複雑化
アプリが扱う状態が増えると、「どの状態がどこで管理されているのか」が分かりにくくなり、開発や保守が困難になります。
-
状態の共有の複雑さ
親コンポーネントから子コンポーネントへ状態を渡す際、いわゆる「バケツリレー」のようなコードが増えてしまい、全体の可読性が低下します。
-
パフォーマンスの問題
状態の変更による不要な再レンダリングが発生し、アプリの動作が遅くなる場合があります。
こうした課題を解決するために、多くの開発現場では状態管理ライブラリが導入されています。状態を一元管理し、コンポーネント間で簡単に共有できるようにすることで、コードの可読性やメンテナンス性が向上します。
Jotaiの知っておきたい4つの基本
Jotaiには、状態管理の中核となる以下の4つの基本的な概念があります。それぞれの役割を具体的に見ていきましょう。
atom
atom はJotaiの基本的な構成要素で、状態管理のための「単位」として機能します。Reactの useState における状態変数に近い役割を果たします。atom()
関数を使って atom 作成し、初期値を渡します。
import { atom } from 'jotai';
// 初期値が0のatomを作成
const countAtom = atom(0);
// 初期値が空の文字列のatomを作成
const textAtom = atom('');
// オブジェクトを初期値に持つatomを作成
const userAtom = atom({ name: 'Alice', age: 25 });
useAtom
useAtom は、作成した atom をコンポーネント内で利用するためのフックです。このフックを使用することで、状態の読み取りや更新が簡単に行えます。Reactの useState に似た使用感で、状態を扱えます。
// 初期値が0のatomを作成
const countAtom = atom(0);
// 作成したatomの状態をuseAtomで使用する
const [value, setValue] = useAtom('');
Provider
Provider は、特定のコンポーネントツリー内で atom の状態を共有するために使用します。Reactの useContext と同じような仕組みを提供します。
デフォルトでは Jotai がアプリ全体で 1 つのグローバルステートを管理しているため、ほとんどの場合、Provider を使わなくても問題ありません。学びはじめのうちは意識する必要はありませんが、概要を知っておくと良いでしょう。
Provider を親コンポーネントでラップすることで、その子孫コンポーネントで atom を利用できるようになります。
import { Provider } from 'jotai';
const App = () => (
<Provider>
<Child />
</Provider>
);
Provider は次に紹介するStore と併用することでその効果を発揮します。
Store
Store は、atom の状態を格納して管理する仕組みです。Jotai では、デフォルトで 1 つの Store が自動的にアプリ全体で用意されており、多くの場合これだけで十分です。Provider と同様に、学びはじめのうちは意識しなくて問題ありません。
カスタム Store が必要になるのは、状態を分けて管理したいときです。以下は Store を作成する例です。
import { Provider, createStore } from 'jotai';
// Storeを作成
const myStore = createStore();
const App = () => (
// ProviderにStoreを適用
<Provider store={myStore}>
<Child />
</Provider>
);
このようにすることで、myStore
に状態が格納され、Provider に作成した Store を指定することで、その範囲で使用される独立した状態を扱えるようになります。
ProviderとStoreの関係性
Provider と Store の役割を簡単に整理すると次の通りです。
- Provider は「状態を提供する範囲」を定義
- Store は「状態を保持する場所」
- Provider に Store を指定することで、その範囲で使用する Store を決定
Provider に Store を指定することで、その範囲で使用する Store を切り替えることができます。複数の Store を使い分けることで、状態管理をスコープごとに分けることが可能です。
以下は複数の Store を使用した例です。
const store1 = createStore();
const store2 = createStore();
// countAtomを定義
const countAtom = atom(0);
function App() {
return (
<div>
<Provider store={store1}>
{/* ここでのcountAtomの値はstore1で管理 */}
<Counter />
</Provider>
<Provider store={store2}>
{/* ここでのcountAtomの値はstore2で管理 */}
{/* store1の値とは独立している */}
<Counter />
</Provider>
</div>
);
}
この例のポイントは、同じ countAtom
を使用していても、store1
と store2
では別々の状態を持つことができます。これにより、異なるスコープで状態を分離して管理することが可能になります。
Jotaiの知っておきたい4つの基本まとめ
このセクションでは、Jotaiの中核となる atom, useAtom, Provider, Store の基本を学びました。以下をポイントとして押さえておきましょう。
-
atom と useAtom
Jotai の基本であり、多くの場面でこの 2 つだけで十分対応可能です。
-
Provider と Store
より高度な状態管理を行いたいときに使用し、状態のスコープを分ける際に役立ちます。
学びはじめのうちは、atom と useAtom の理解に集中し、Provider や Store は必要性が出てきたときに徐々に取り入れると良いでしょう。
次のセクションでは、atom と useAtom を活用した具体的な使用方法を解説します。
Jotaiの使い方
ここでは、Jotaiを使った状態管理の基本的な流れを解説します。インストールから簡単なカウンターアプリの実装までを解説します。
1. Jotaiのインストール方法
まず、ReactプロジェクトにJotaiをインストールします。以下のコマンドをプロジェクトのルートディレクトリで実行してください。
npm install jotai
yarn
を使っている場合は以下を実行します。
yarn add jotai
インストールが完了したら、次のステップに進みます。
2. atom の定義
次に状態を管理する atom を定義します。atom は、Reactコンポーネント間で共有できる「グローバルな状態」を表します。
以下の例では初期値が 0
のカウント状態を管理する atom を作成しています。
import { atom } from 'jotai'
// 状態を管理するatomを作成
const countAtom = atom(0);
atom は、useState
の状態変数と似ていますが、複数のコンポーネント間で共有できる状態として機能します。初期値を指定することで、状態の初期値を設定できます。
3. useAtomで状態を取得・更新
作成した atom を使うには、useAtom フックを利用します。このフックで、状態の 取得(読み取り) と 更新(書き込み) が行えます。
以下は、カウントアップボタン機能をJotaiで実装した例です。
// App.jsx
import { atom, useAtom } from 'jotai';
// 状態を管理するatomを作成
const countAtom = atom(0);
function App() {
// useAtomで状態を取得・更新
const [count, setCount] = useAtom(countAtom);
return (
<>
<h2>Jotai カウンター</h2>
<button onClick={() => setCount(count + 1)}>+1</button>
<p>現在のカウント: {count}</p>
</>
);
}
export default App;
4. Jotaiのシンプルさと初心者へのメリット
useState と似た記述で、useAtom を使って状態管理ができるため、初心者の方にも馴染みやすいかと思います。atom で定義した状態は、どのコンポーネントからでも簡単にアクセスできるため、アプリ全体での状態共有が容易です。
Jotaiを使ったハンズオンで理解を深める
ここまでJotaiの基本と使い方を学びました。このセクションではJotaiを使用したTodoアプリをハンズオン形式で作成し、状態管理の理解をさらに深めます。
Reactの開発環境の構築について、この記事では紹介していません。以下の記事で詳しく解説していますので、ぜひご覧ください。
【超入門】Reactの基礎を30分で学べる!インストールから基本コンポーネントまで
https://envader.plus/article/341
Todoアプリの概要
今回のハンズオンでは、以下のような機能を持つシンプルなTodoアプリを作成します。
- タスクの追加
- タスクの表示
- タスクの完了状態の切り替え
状態管理がアプリの中心になるため、Jotaiの特徴を学ぶのに最適な題材です。
Todoアプリの完成イメージ
ファイル構成
以下の4つのファイルを使用してアプリを構築します。
-
App.jsx
アプリのメインコンポーネント
-
atoms.js
グローバル状態(atom)を定義するファイル
-
AddTask.jsx
新しいタスクを追加するコンポーネント
-
TaskList.jsx
タスクを一覧表示するコンポーネント
Jotaiを使用したTodoアプリの作成
はじめにRectプロジェクトを作成し、Jotaiをインストールした開発環境を構築します。
ハンズオンの実装
それぞれのファイルを編集します。
App.jsx
Todoアプリの親コンポーネントにあたるファイルです。Todoの状態をatomや、他のコンポーネントにモジュールを分離することで、シンプルな記述内容になっています。
// App.jsx
import React from 'react';
import AddTask from './AddTask';
import TaskList from './TaskList';
const App = () => {
return (
<div>
<h1>ToDo Lists</h1>
<AddTask />
<TaskList />
</div>
);
};
export default App;
atoms.js
このファイルではatomを記述し、状態を他のファイルとグローバルに管理できるようにしています。他のファイルにatoms.jsをインポートすることで、状態をフローバルに扱えます。
// atoms.js
import { atom } from 'jotai';
// タスクのリストを管理するグローバルな状態
// Jotaiのatomを使用して、タスクの配列をアプリ全体で共有
export const taskListAtom = atom([]);
AddTask.jsx
タスク追加の機能を記述しているコンポーネントです。atoms.jsファイルをインポートすることで、親コンポーネントから状態をpropsで受け取る記述を省略することができています。
// AddTask.jsx
import React, { useState } from 'react';
import { useSetAtom } from 'jotai';
import { taskListAtom } from './atoms';
const AddTask = () => {
const [task, setTask] = useState('');
// JotaiのuseSetAtomで、taskListAtomの状態を更新する関数を取得
const addTask = useSetAtom(taskListAtom);
const handleAddTask = () => {
if (task.trim()) {
// 新しいタスクを追加し、Jotaiのatomに保存
addTask((prevTasks) => [...prevTasks, { id: Date.now(), text: task, completed: false }]);
setTask(''); // 入力フィールドをリセット
}
};
return (
<div>
<input
type="text"
value={task}
onChange={(e) => setTask(e.target.value)}
placeholder="タスクを入力してください"
/>
<button onClick={handleAddTask}>Add</button>
</div>
);
};
export default AddTask;
TaskList.jsx
このファイルは、AddTask.jsxで追加したTodoリストの状態を表示させるコンポーネントです。このファイルもatom.jsをインポートすることで、状態を簡単に受け取っています。
// TaskList.jsx
import React from 'react';
import { useAtom } from 'jotai';
import { taskListAtom } from './atoms';
const TaskList = () => {
// useAtomでtaskListAtomを参照し、現在のタスク一覧と更新関数を取得
const [tasks, setTasks] = useAtom(taskListAtom);
const toggleTask = (id) => {
// タスクの完了状態を切り替え
setTasks((prevTasks) =>
prevTasks.map((task) =>
task.id === id ? { ...task, completed: !task.completed } : task
)
);
};
return (
<ul>
{tasks.map((task) => (
<li
key={task.id}
// 完了状態に応じて表示を切り替え
style={{
textDecoration: task.completed ? 'line-through' : 'none',
cursor: 'pointer',
}}
onClick={() => toggleTask(task.id)} // タスクの完了切り替え
>
{task.text}
</li>
))}
</ul>
);
};
export default TaskList;
全てのファイルを編集後、以下のようにタスクを追加できるTodoアプリが作成できているかと思います。※以下のイメージ図は別にCSSを適用しています。
ハンズオンまとめと今後のステップアップ
今回のハンズオンでは、Jotaiを使った状態管理のシンプルさを体験していただきました。状態をグローバルに管理することで、モジュールをファイルごとに分離しやすくなり、全体のコード構成が整ったのではないでしょうか。
Jotaiのメリットの振り返り
-
状態管理が簡潔
状態をグローバルに管理することで、propsの受け渡しを省略できます。
-
モジュール化しやすい構造
機能ごとにファイルを分けて管理することが容易になります。
次のステップとして、以下のような機能を追加してJotaiの理解を深めてみてください。
- タスクの検索機能
- タスクの削除機能
- 完了済みタスクのフィルタリング
これらの機能を通じて、さらにJotaiの柔軟さや使いやすさを実感していただければ幸いです。
この記事で学んだこと
この記事では、Reactの状態管理ライブラリJotaiについて、基本的な使い方からハンズオンでのアプリ開発までを学びました。最後に大切なポイントを振り返りましょう。
Jotaiとは?
Jotai は、Reactで使えるシンプルな状態管理ライブラリです。useState のように直感的に状態を扱え、状態を「atom(アトム)」という小さな単位に分割して管理します。この仕組みにより、不要な再レンダリングを防ぎ、コードをスッキリと保つことができます。
Jotaiの4つの基本的な概念
Jotaiを使いこなすために必要な4つの基本を学びました。
-
atom
状態を管理するための最小単位で、Jotaiの基本的な構成要素です。
-
useAtom
atomをReactコンポーネント内で利用するためのフックです。
-
Provider
特定のコンポーネントツリー内でatomの状態を共有するために使用します。
-
Store
atomの状態を格納して管理する仕組みで、より複雑な状態管理が可能です。
実践することで理解が深まる
Jotai は、シンプルな記述で柔軟な状態管理を提供する便利なライブラリです。この記事で学んだ知識をもとに、ぜひ実際に手を動かしてアプリ開発に挑戦してみてください。小さなアプリから始めることで、理解が深まり、できることが増えていきます。
「まずやってみる」という一歩が、新しいスキルを身につける最大のきっかけです。この機会にJotaiを活用して、自分だけのアプリを作る楽しさを体験していただければ幸いです。
参照資料
-
Jotai公式
-
Jotai Friends
-
Daishi Kato's blog - Thoughts on State Management Libraries in the React Compiler Era
https://blog.axlight.com/posts/thoughts-on-state-management-libraries-in-the-react-compiler-era/
【番外編】USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話

プログラミング塾に半年通えば、一人前になれると思っているあなた。それ、勘違いですよ。「なぜ間違いなの?」「正しい勉強法とは何なの?」ITを学び始める全ての人に知って欲しい。そう思って書きました。是非読んでみてください。
「フリーランスエンジニア」
近年やっと世間に浸透した言葉だ。ひと昔まえ、終身雇用は当たり前で、大企業に就職することは一種のステータスだった。しかし、そんな時代も終わり「優秀な人材は転職する」ことが当たり前の時代となる。フリーランスエンジニアに高価値が付く現在、ネットを見ると「未経験でも年収400万以上」などと書いてある。これに釣られて、多くの人がフリーランスになろうとITの世界に入ってきている。私もその中の1人だ。数年前、USBも知らない状態からITの世界に没入し、そこから約2年間、毎日勉学を行なった。他人の何十倍も努力した。そして、企業研修やIT塾で数多くの受講生の指導経験も得た。そこで私は、伸びるエンジニアとそうでないエンジニアをたくさん見てきた。そして、稼げるエンジニア、稼げないエンジニアを見てきた。
「成功する人とそうでない人の違いは何か?」
私が出した答えは、「量産型エンジニアか否か」である。今のエンジニア市場には、量産型エンジニアが溢れている!!ここでの量産型エンジニアの定義は以下の通りである。
比較的簡単に学習可能なWebフレームワーク(WordPress, Rails)やPython等の知識はあるが、ITの基本概念を理解していないため、単調な作業しかこなすことができないエンジニアのこと。
多くの人がフリーランスエンジニアを目指す時代に中途半端な知識や技術力でこの世界に飛び込むと返って過酷な労働条件で働くことになる。そこで、エンジニアを目指すあなたがどう学習していくべきかを私の経験を交えて書こうと思った。続きはこちらから、、、、
エンベーダー編集部
エンベーダーは、ITスクールRareTECHのインフラ学習教材として誕生しました。 「遊びながらインフラエンジニアへ」をコンセプトに、インフラへの学習ハードルを下げるツールとして運営されています。

関連記事

2020.02.25
完全未経験からエンジニアを目指す爆速勉強法
USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話
- キャリア・学習法
- エンジニア

2024.06.30
Reactの基本、コンポーネントを理解する
フロントエンドエンジニアになりたい、初めてReactを学ぶ方に向けて、この記事ではReactの基本であるコンポーネントについて解説していきます。コンポーネントを学ぶことで、これからのReact学習の理解度が深まります。基本を学び、フロントエンドエンジニアへの道を進んでいきましょう!
- React

2024.08.24
Reactの基本、useContextを理解しよう
今回は、コンポーネント間でデータを共有するのに役立つuseContextについて解説します。
- React
- フロントエンド

2024.08.17
Reactの基本、useEffectを理解しよう
フロントエンドエンジニアを目指す方や、初めてReactを学ぶ方に向けて、この記事ではReact HooksのuseEffectについて解説します。useEffectの仕組みは少し複雑で初学者の方にとって難しく感じるかもしれませんが、Reactでの開発では必須の技術となります。useEffectの基本を押さえておくことで、これからのReact学習の理解度が深まります。基本を学び、フロントエンドエンジニアへの道を進んでいきましょう!
- プログラミング
- React
- フロントエンド