Jotai 使用详解:React 轻量级状态管理库

Jotai 是一个 React 全局状态管理库,以其原子化模型和简洁 API 著称。它类似于 Recoil,但更加轻量且易于使用。下面我将详细介绍 Jotai 的核心概念和使用方法。

Jotai 官方文档

1. 基础用法

创建原子 (Atom)

原子是 Jotai 中的基本状态单元:

js 复制代码
import { atom } from 'jotai';

// 创建一个原子
const countAtom = atom(0); // 初始值为0

使用原子

在组件中使用 useAtom hook:

js 复制代码
import { useAtom } from 'jotai';

function Counter() {
  const [count, setCount] = useAtom(countAtom);
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

2. 派生原子

Jotai 允许创建基于其他原子的派生状态:

js 复制代码
const doubleCountAtom = atom((get) => get(countAtom) * 2);

function DisplayDouble() {
  const [doubleCount] = useAtom(doubleCountAtom);
  return <p>Double count: {doubleCount}</p>;
}

3. 异步原子

Jotai 支持异步操作:

js 复制代码
const fetchUserAtom = atom(async () => {
  const response = await fetch('https://api.example.com/user');
  return response.json();
});

function UserProfile() {
  const [user] = useAtom(fetchUserAtom);
  
  if (!user) return <div>Loading...</div>;
  
  return (
    <div>
      <h2>{user.name}</h2>
      <p>{user.email}</p>
    </div>
  );
}

4. 写入派生原子

可以创建既可读又可写的派生原子:

js 复制代码
const countAtom = atom(0);
const incrementCountAtom = atom(
  (get) => get(countAtom),
  (get, set, _arg) => {
    set(countAtom, get(countAtom) + 1);
  }
);

function Counter() {
  const [count, increment] = useAtom(incrementCountAtom);
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
}

5. 实用功能

原子组合

js 复制代码
const firstNameAtom = atom('John');
const lastNameAtom = atom('Doe');

const fullNameAtom = atom((get) => {
  return `${get(firstNameAtom)} ${get(lastNameAtom)}`;
});

本地存储持久化

js 复制代码
import { atomWithStorage } from 'jotai/utils';

const themeAtom = atomWithStorage('theme', 'light');

function ThemeToggle() {
  const [theme, setTheme] = useAtom(themeAtom);
  
  return (
    <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
      Toggle Theme (Current: {theme})
    </button>
  );
}

6. Provider 使用

虽然 Jotai 有默认的全局 store,但也可以创建隔离的 context:

js 复制代码
import { Provider } from 'jotai';

function App() {
  return (
    <Provider>
      <Counter />
      <DisplayDouble />
    </Provider>
  );
}

7. 最佳实践

  1. 原子粒度:保持原子小而专注
  2. 派生状态:使用派生原子而不是在组件中计算
  3. 性能优化 :使用 useAtomValueuseSetAtom 分离读写
  4. 类型安全:Jotai 完全支持 TypeScript

8. 与其它库比较

特性 Jotai Recoil Zustand Redux
学习曲线
包大小 很小(~3KB) 小(~14KB) 小(~5KB) 中(~16KB)
原子模型 ✔️ ✔️
异步支持 ✔️ ✔️ ✔️ 需要中间件
Context 可选 需要 不需要 不需要

9. 实际应用示例

js 复制代码
// atoms.js
export const todosAtom = atom([]);
export const filterAtom = atom('all');

export const filteredTodosAtom = atom((get) => {
  const todos = get(todosAtom);
  const filter = get(filterAtom);
  
  return filter === 'all' 
    ? todos 
    : todos.filter(todo => filter === 'completed' ? todo.completed : !todo.completed);
});

// TodoList.jsx
function TodoList() {
  const [todos] = useAtom(filteredTodosAtom);
  const [, setTodos] = useAtom(todosAtom);
  
  const addTodo = (text) => {
    setTodos(prev => [...prev, { text, completed: false }]);
  };
  
  // ...渲染逻辑
}

Jotai 的简洁性和灵活性使其成为中小型 React 应用的理想状态管理解决方案,特别是当你需要细粒度状态控制而不想处理复杂样板代码时。

相关推荐
kyriewen7 小时前
我手写了一个 EventEmitter,面试官追问了 6 个问题——第 4 个我没答上来
前端·javascript·面试
IT_陈寒8 小时前
Java的Date类又坑了我一次,改用时间戳真香
前端·人工智能·后端
小林攻城狮8 小时前
使用 Transport 节流解决 Vercel AI SDK 流式渲染卡死问题
前端·react.js
前端缘梦8 小时前
告别 TS 运行时类型漏洞!Zod 完整入门实战教程(前端 / 全栈必备)
前端·react.js·全栈
the_answer9 小时前
Webpack vs Vite 深度对比分析
前端·webpack
转转技术团队9 小时前
验证码识别实战:前端不写页面,改训模型了?
前端
MomentYY9 小时前
Temperature:AI 的“脑洞旋钮”
前端·llm·ai编程
远航_9 小时前
OpenSpec 完整详细介绍
前端·后端
召钱熏9 小时前
状态枚举正确≠渲染正确:一个语音按钮的状态机边界修复实录
android·前端
SkyWalking中文站9 小时前
认识 Horizon UI · 1/17:SkyWalking 新一代可观测性控制台
运维·前端·监控