最小化的React状态管理库:Jotai介绍及使用教程
很长时间以来,Redux一直是React中全局状态管理的领导库。但随着钩子的引入,我发现像react-query或useSWR()这样的库以较少的模板处理数据的获取。
但简单的UI状态,如侧边菜单的展开、主题、黑暗模式等需要单独的管理--在这种情况下,像Jotai
(https://github.com/pmndrs/jotai)这样简单的全局状态管理库就变得很方便。
在这篇文章中,你将学习如何使用Jotai
。
目录
1.搜索查询:一个全局状态变量
一个应用程序有一个标题和主要内容组件。头部组件有一个输入字段,用户可以在那里引入一个搜索查询。主组件应该显示输入字段中引入的搜索查询。
这里是应用程序的初始草图:
import { useState } from 'react';
function App() {
return (
<div>
<Header />
<Main />
</div>
);
}
function Header() {
const [search, setSearch] = useState('');
const handleChange = event => setSearch(event.target.value);
return (
<header>
<input type="text" value={search} onChange={handleChange} />
</header>
);
}
function Main() {
// How to access the search?
return <main>Search query: ???</main>;
}
<App>
是由2个组件组成: <Header>
和 <Main>
。
<Header>
是一个包含输入字段的组件,用户在该字段中引入一个搜索查询。
<Main>
是一个组件,它应该呈现输入字段中的查询。你将如何访问这里的值?
搜索查询是一个全局状态变量。而Jotai
库在这里可以使用一个名为atom的结构帮助你。
2.Jotai atoms
Jotai
中的一块状态是由一个原子表示的。一个原子接受一个初始值,无论是像数字、字符串这样的原始类型,还是像数组和对象这样更复杂的结构。
import { atom } from 'jotai';
const counterAtom = atom(0);
counterAtom
是持有计数器状态的原子。
但是光有原子并没有什么用。为了读取和更新原子的状态,Jotai
提供了一个特殊的钩子useAtom()
。
import { atom, useAtom } from 'jotai';
export const counterAtom = atom(0);
export function CounterButton() {
const [count, setCount] = useAtom(counterAtom);
const handleClick = () => {
setCount(number => number + 1); // Increment number
};
return (
<div>
{count}
<button onClick={handleClick}>Increment</button>
</div>
);
}
const [count, setCount] = useAtom(counterAtom)
返回一个元组,其中第一项是状态的值,第二项是一个状态更新器函数。
count
包含原子的值,而 setCount()
可以用来更新原子的值。
原子的卖点在于,你可以从多个组件中访问同一个原子。如果一个组件更新了该原子,那么所有读取该原子的组件都会被更新。这就是全局的状态管理!
例如,让我们在另一个组件中读取counterAtom
的值<CurrentCount>
:
import { useAtom } from 'jotai';
import { counterAtom } from './Button';
function CurrentCount() {
const [count] = useAtom(counterAtom);
return <div>Current count: {count}</div>;
}
当counterAtom
的值发生变化时(由于计数器的增量),那么<CounterButton>
和<CurrentCount>
两个组件都将重新渲染。
useAtom(atom)
钩子的伟大之处在于保持了与内置的useState()
钩子相同的API--它也会返回一个状态值的元组和一个更新器函数。
2.1 搜索查询原子
<Main>
现在让我们回到第一节的问题:如何在<Header>
组件中共享搜索查询。
你可能已经看到了解决方案:让我们创建一个原子searchAtom
,并在<Header>
和<Main>
组件之间共享它。
import { useState } from 'react';
import { atom, useAtom } from 'jotai';
function App() {
return (
<div>
<Header />
<Main />
</div>
);
}
const searchAtom = atom('');
function Header() {
const [search, setSearch] = useAtom(searchAtom);
const handleChange = event => setSearch(event.target.value);
return (
<header>
<input type="text" value={search} onChange={handleChange} />
</header>
);
}
function Main() {
const [search] = useAtom(searchAtom);
return <main>Search query: "{search}"</main>;
}
const searchAtom = atom('')
创建一个原子,用来保存搜索查询的全局状态变量。
在<Header>
组件内部const [search, setSearch] = useAtom(searchAtom)
,返回当前的搜索值,以及更新器函数。
只要用户在输入框中输入,handleChange()
事件处理程序就会更新原子的值:setSearch(event.target.value)
。
<Main>
组件也可以访问 的值: 。而当原子的值由于用户在输入框中打字而发生变化时, 组件会被更新以接收新的值。searchAtom
const [search] = useAtom(searchAtom)
<Main>
总之,原子是全局性的状态片段,可以被任何组件访问和修改。
3.Jotai衍生的原子
如果你发现自己从一个原子的值中计算数据,那么你可能会发现Jotai
的派生原子功能很有用。
你可以在向atom(get => get(myAtom))
提供回调函数时创建一个派生原子:在这种情况下,Jotai
通过一个 getter 函数get
调用回调,你可以从那里提取基础原子的值get(myAtom)
。
import { atom } from 'jotai';
const numberAtom = atom(2);
const isEvenAtom = atom(get => get(numberAtom) % 2 === 0);
在上面的例子中,numberAtom
持有一个数字。isEvenAtom
是一个派生原子,它决定存储在numberAtom
的数字是否是偶数。
当然,一旦基础原子发生变化,派生原子也会发生变化。
例如,让我们创建isNameEmptyAtom
派生原子,确定存储在nameAtom
的字符串是空的。
import { atom, useAtom } from 'jotai';
const nameAtom = atom('Batman');
const isNameEmptyAtom = atom(get => get(nameAtom).length === 0);
function HeroName() {
const [name, setName] = useAtom(nameAtom);
const [isNameEmpty] = useAtom(isNameEmptyAtom);
const handleChange = event => setName(event.target.value);
return (
<div>
<input type="text" value={name} onChange={handleChange} />
<div>Is name empty: {isNameEmpty ? 'Yes' : 'No'}</div>
</div>
);
}
更棒的是,你可以从多个基原子中创建一个派生原子!
import { atom } from 'jotai';
const counterAtom1 = atom(0);
const counterAtom2 = atom(0);
const sumAtom = atom((get) => get(counterAtom1) + get(counterAtom2));
sumAtom
是由 2 个基体原子派生出来的:counterAtom1
和 counterAtom2
。
4.总结
我喜欢Jotai
,因为它以极简但灵活的方式来管理一个简单的全局状态。
要创建一个全局状态变量,你需要两个步骤。
A) 为你的全局状态变量定义一个原子:
const myAtom = atom(<initialValue>);
B) 然后使用特殊的钩子useAtom(<atom>)
,在组件内部访问原子的值和更新器函数:
function MyComponent() {
const [value, setValue] = useAtom(myAtom);
// ...
}
我发现Jotai
很适合管理简单的全局变量,作为异步状态管理库的补充,如react-query
和useSWR()
。
这篇文章描述了Jotai
的基本功能。请访问资源库github.com/pmndrs/jota…,阅读所有的功能。
你会用Jotai
来管理简单的全局状态变量吗?在你看来,这个库还缺少哪些功能?
转载自:https://juejin.cn/post/7126026221678395422