likes
comments
collection
share

最小化的React状态管理库:Jotai介绍及使用教程

作者站长头像
站长
· 阅读数 56

很长时间以来,Redux一直是React中全局状态管理的领导库。但随着钩子的引入,我发现像react-queryuseSWR()这样的库以较少的模板处理数据的获取。

但简单的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> 两个组件都将重新渲染。

最小化的React状态管理库:Jotai介绍及使用教程

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 的数字是否是偶数。

最小化的React状态管理库:Jotai介绍及使用教程

当然,一旦基础原子发生变化,派生原子也会发生变化。

例如,让我们创建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 个基体原子派生出来的:counterAtom1counterAtom2

最小化的React状态管理库:Jotai介绍及使用教程

4.总结

我喜欢Jotai ,因为它以极简但灵活的方式来管理一个简单的全局状态。

要创建一个全局状态变量,你需要两个步骤。

A) 为你的全局状态变量定义一个原子:

const myAtom = atom(<initialValue>);

B) 然后使用特殊的钩子useAtom(<atom>) ,在组件内部访问原子的值和更新器函数:

function MyComponent() {
  const [value, setValue] = useAtom(myAtom);
  // ...
}

我发现Jotai 很适合管理简单的全局变量,作为异步状态管理库的补充,如react-queryuseSWR()

这篇文章描述了Jotai 的基本功能。请访问资源库github.com/pmndrs/jota…,阅读所有的功能。

你会用Jotai 来管理简单的全局状态变量吗?在你看来,这个库还缺少哪些功能?

转载自:https://juejin.cn/post/7126026221678395422
评论
请登录