初步了解轻量高效的 React 状态库 Jotai
Jotai 是什么
Jotai 是状态管理库,原子化思想,提供一个最基础的原子,通过组合原子来构建状态,并且基于原子依懒性进行优化渲染,避免了 React 额外的渲染。Atom 在 Jotai 中是状态单位(原子),可以更新也可以被组件订阅(使用useAtom
),当 Atom 更新了,那么订阅这个 Atom 的组件便会重新渲染。
- 创建原子过程就和使用 useState Hook 一样简单方便,并且全局可用的。
const nameAtom = atom('chenjiang')
。
- 使用灵活:可以基于这个或者一些原子,从而衍生出更多状态。
Jotai 适用场景
中小型项目:Jotai 设计的目标就是轻量且易用,适合中小型项目,不需要复杂的状态管理。
需要局部状态管理:Jotai 采用原子状态概念,意味着可以将状态拆解为独立的、可组合的原子单元。不需要全局状态管理库的复杂性。
组件间的状态传递:Jotai 可以让多个组件共享相同的原子状态,并且支持同步更新和跨组件传递状态。可以减少 Context 或者 Props 传递过程的繁琐及产生不必要的渲染。
高效的异步操作:Jotai 支持异步操作,使用 atom
配合异步函数,可以优雅的管理数据状态。
替代 Context 或 Redux:Jotai 是一个更加简洁的状态管理工具,可以替代复杂的 Context 和 Redux,尤其当项目不需要全局状态或者深层的状态管理时。
开发者希望拥有更细粒度控制场景:Jotai 的原子状态机制允许你精确的控制每个状态更新和影响范围。相比传统的 Redux,没有过多的样板代码,提供了更高的灵活性。
需要状态持久化:Jotai 提供 API 可以与localStorage
和sessionStorage
配合,支持状态持久化到客户端。
s
Jotai 设计理念
原子化:将状态拆分为小的、独立的单元,Jotai 是状态变的更加准确,从而提高了性能和可维护性。每个组件只会重新渲染它所依赖的原子,而不是整个应用。
React 原生集成:不需要引入复杂的方法,直接能够与 React 现有的功能集成。学习曲线低,避免了传统的状态管理库的复杂配置和样板代码,更容易上手。
细粒度的状态管理:状态细分为多个小的原子,每个原子代表一个特定的、独立的状态单元,开发者可以灵活的组合和管理这些原子。通过这种状态管理,Jotai 能够更加精确的控制,每个原子的更新只会影响那些依赖它的组件,避免了不必要的渲染,从而提高应用性能。
更好的异步操作:Jotai 支持异步原子的创建,可以将异步操作集成到原子中。不需要再为异步操作编写额外的逻辑或者使用特殊的中间件(例如:Redux Thunk),只需要将异步操作封装为原子即可。
初步体验原子状态
和 useState 类似,useAtom 会返回一个最新的原子状态和修改原子状态的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import { atom, useAtom } from "jotai"; import "./App.css";
const nameAtom = atom("chenjiang");
function App() { const [name, setName] = useAtom(nameAtom);
return ( <> <button onClick={() => { setName(name + "123"); // 更新原子的值 }} > 修改name </button> <h1>{name}</h1> </> ); } export default App;
|
原子可组合性(基于原子衍生出更多状态)
某个原子依赖另外一个原子,当依赖的原子更新了,那么当前的原子也随之更新。
例如:name 大写这个 atom 它本身依赖 name,当最基础的 name 发生了变化,name 大写也会更新,订阅此原子的组件也重新渲染。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| const nameAtom = atom("chenjiang");
const nameUppercaseAtom = atom((get) => get(nameAtom).toUpperCase());
const Uppercase = () => { const [uppercaseName] = useAtom(nameUppercaseAtom); return <h1>{uppercaseName}</h1>; };
function App() { const [name, setName] = useAtom(nameAtom);
return ( <> <button onClick={() => { setName(name + "666"); }} > 修改name </button> <Uppercase /> </> ); }
|
状态持久化
一般来说页面刷新后,所有的状态都丢失,都恢复成初始值。Jotai 提供了一个工具方法atomWithStorage
,保留原子状态到 localStorage(默认)。
localstorage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import { useAtom } from "jotai"; import { atomWithStorage } from "jotai/utils";
const nameAtom = atomWithStorage("name", "chenjiang");
function App() { const [name, setName] = useAtom(nameAtom);
return ( <> <button onClick={() => { setName(name + "666"); }} > 修改name </button> <h1>{name}</h1> </> ); }
|
自定义存储
1 2 3 4 5 6 7 8 9
| const sessionStorageAtom = atomWithStorage( "sessionKey", "defaultValue", { getItem: (key) => {}, setItem: (key, value) => {}, removeItem: (key) => {}, } );
|
sessionStorage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import { useAtom } from "jotai"; import { atomWithStorage, createJSONStorage } from "jotai/utils";
const storage = createJSONStorage(() => sessionStorage); const nameAtom = atomWithStorage("name", "chenjiang", storage);
function App() { const [name, setName] = useAtom(nameAtom);
return ( <> <button onClick={() => { setName(name + "666"); }} > 修改name </button> <h1>{name}</h1> </> ); }
|
可复原的原子状态
通过atomWithReset
定义可还原原子,再通过useResetAtom
hook 创建一个可还原的方法。
类似表单的重置功能,对原子进行一系列更新之后复原,回到最初始状态。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import { useAtom } from "jotai"; import { atomWithReset, useResetAtom } from "jotai/utils";
const nameAtom = atomWithReset("chenjiang");
function App() { const [name, setName] = useAtom(nameAtom); const resetName = useResetAtom(nameAtom);
return ( <> <button onClick={() => { setName(name + "666"); }} > 修改name </button> <button onClick={resetName}>复原</button> <h1>{name}</h1> </> ); }
|