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 应用的理想状态管理解决方案,特别是当你需要细粒度状态控制而不想处理复杂样板代码时。

相关推荐
IT_陈寒3 小时前
Redis性能翻倍的5个冷门技巧,90%开发者都不知道第3个!
前端·人工智能·后端
jingling5555 小时前
vue | 在 Vue 3 项目中集成高德地图(AMap)
前端·javascript·vue.js
油丶酸萝卜别吃5 小时前
Vue3 中如何在 setup 语法糖下,通过 Layer 弹窗组件弹出自定义 Vue 组件?
前端·vue.js·arcgis
J***Q29211 小时前
Vue数据可视化
前端·vue.js·信息可视化
ttod_qzstudio13 小时前
深入理解 Vue 3 的 h 函数:构建动态 UI 的利器
前端·vue.js
_大龄13 小时前
前端解析excel
前端·excel
一叶茶14 小时前
移动端平板打开的三种模式。
前端·javascript
前端大卫14 小时前
一文搞懂 Webpack 分包:async、initial 与 all 的区别【附源码】
前端
Want59514 小时前
HTML音乐圣诞树
前端·html
老前端的功夫14 小时前
前端浏览器缓存深度解析:从网络请求到极致性能优化
前端·javascript·网络·缓存·性能优化