Jotai使用笔记(一)

chatgpt/2023/9/26 13:28:29

Jotai

Jotai 是一款轻量级的状态管理工具,大小只有2kb,支持 Typescript。

1. Jotai的组成部分

  1. store: 主要用于数据的存储、依赖的收集和更新,已经更新通知
  2. atom:创建原子,或者衍生新的原子
  3. useAtom:将atom与视图关联起来(将atom与store链接起来,同时订阅store中atom得变化)
  4. Provider: 传图store来隔离数据,如果不传将使用默认store

2 atom

首先看一下atom的创建函数

// primitive atom
function atom<Value>(initialValue: Value): PrimitiveAtom<Value>// read-only atom
function atom<Value>(read: (get: Getter) => Value | Promise<Value>): Atom<Value>// writable derived atom
function atom<Value, Update>(read: (get: Getter) => Value | Promise<Value>,write: (get: Getter, set: Setter, update: Update) => void | Promise<void>
): WritableAtom<Value, Update>// write-only derived atom
function atom<Value, Update>(read: Value,write: (get: Getter, set: Setter, update: Update) => void | Promise<void>
): WritableAtom<Value, Update>

如上代码atom分为:原始atom、衍生atom、只读atom、只写atom,以及可读可写atom。

const primitiveAtom = atom(initialValue)
const derivedAtomWithRead = atom(read)
const derivedAtomWithReadWrite = atom(read, write)
const derivedAtomWithWriteOnly = atom(null, write)

下面创建了原始atom countAtom,衍生atom deriveAtom,当countAtom中的值发生变化时deriveAtom的值会自动更新。

import { atom } from 'jotai'// 原始atom
const countAtom = atom(10)
// 衍生atom,依赖另一个atom
const deriveAtom = atom((get) => get(countAtom) * 2);
// 只读
const readOnlyAtom = atom((get) => get(countAtom) * 2);
// 只写
const writeOnlyAtom =  atom(null, (get, set, update) => set(countAtom, get(countAtom) * update));
// 可读可写
const readWriteAtom = atom((get) => get(countAtom) * 2,(get, set, update) => {set(countAtom, update / 2)}
)

2.1 useAtom

useAtom用于读取atom状态中的值,atom的状态数据保存在store的WeakMap中。像React的useState一样,useAtom以元组的方式返回值和更新函数。

atom最初是没有值的,当atom第一次被useAtom使用时,初始值才会存储在state中。如果atom是衍生的,read函数将会被调用以此来计算初始值。当atom不再被使用时,意味着所有使用它的组件都被卸载了,状态中值将被垃圾回收。

const [value, setValue] = useAtom(countAtom)

如果只是想获取atom的值,不需要修改,可以使用 useAtomValue:

const count = useAtomValue(countAtom)

同理,如果只想更新atom,不需要获取值,使用 useSetAtom:

 const setCount = useSetAtom(countAtom)

3 store

在store中存储atom的状态,store可以作为value传入Provider,store提供如下三个方法:

  • get:获取atom的值
  • set:设置atom的值
  • sub:订阅atom的更新,当atom值发生改变后会调用订阅的函数, useAtomValue的源码中就通过该方法来触发组件的更新。
const myStore = createStore()const Root = () => (<Provider store={myStore}><App /></Provider>
)

如果没有提供Provier,就会使用默认的store,称为Provider-less模式。
默认store创建函数:

const defaultStore = getDefaultStore()

useAtomValueuseSetAtom举例,其中都会使用useStore,useStore如果没有传入store并且StoreContext中也没store的话就使用默认store。源码如下:

const StoreContext = createContext<Store | undefined>(undefined)export const useStore = (options?: Options): Store => {const store = useContext(StoreContext)return options?.store || store || getDefaultStore()
}

没使用Provider组件时,StoreContext的值为undefined,这时就调用getDefaultStore获取默认store。

Provider

Provider组件使用React Context为组件的子树提供状态,多个Provider可以为多个子树提供状态,并且可以嵌套使用。
如果atom没有在provider下使用,就使用默认store,称之为Provider-less模式。

Provider的作用有一下三点:

  1. 为不同的子树提供不同的状态。
  2. 接受atom的初始值
  3. 通过重新挂载清除所有原子
const SubTree = () => (<Provider><Child /></Provider>
)

Provider的类型签名

const Provider: React.FC<{store?: Store
}>

atom的值并不在atom自身,而是保存在对应的store中,Provider是一个包含store并为子组件的atom提供值的组件。如果需要给不同的子树提供不同的atom值设置Provider是很有必要的。

举例:

// app.tsx
const myStore = createStore()const Root = () => (<Provider store={myStore}><App /></Provider>
)
// component.tsx
const Component = () => {const store = useStore()const [count, setCount] = useAtom(countAtom, {store})// ...
}

useStore的第二个参数可以指定从哪个store中获取atom的值,如果不传就从StoreContext中取,StoreContext中没有就使用默认的store。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.exyb.cn/news/show-5314245.html

如若内容造成侵权/违法违规/事实不符,请联系郑州代理记账网进行投诉反馈,一经查实,立即删除!

相关文章

日撸代码300行:第58天(符号型数据的 NB 算法)

代码来自闵老师”日撸 Java 三百行&#xff08;51-60天&#xff09;“&#xff0c;链接&#xff1a;https://blog.csdn.net/minfanphd/article/details/116975957 Naive Bayes是通过概率分布来进行分类。基础理论知识见闵老师博客[1]&#xff1a;NB 算法 (包括符号型与数值型,…

【ES】使用日志记录

1、修改操作 1、要删除Elasticsearch索引的分区下的数据 <index_name>是要删除数据的索引名称。这个命令会删除该索引下的所有数据。 POST /<index_name>/_delete_by_query {"query": {"match_all": {}} }2、删除特定条件下的数据 要删除a…

代码随想录 day44 完全背包

class Solution { public: int change(int amount, vector<int>& coins) { vector <int> dp(amount1,0); dp[0]1; for(int i0;i<coins.size();i){ for(int jcoins[i];j<amount;j){ dp[j]dp[j-coins[i]]; } } return dp[amount]; } }; 另外你这个是不能…

【TypeScript】接口类型 Interfaces 的使用理解

导语&#xff1a; 什么是 类型接口&#xff1f; 在面向对象语言中&#xff0c;接口&#xff08;Interfaces&#xff09;是一个很重要的概念&#xff0c;它是对行为的抽象&#xff0c;而具体如何行动需要由类&#xff08;classes&#xff09;去实现&#xff08;implement&#x…

C语言【怎么定义变量?】

变量定义的目的是向编译器说明在哪里创建变量的存储&#xff0c;并指明如何创建变量的存储方式。变量定义会明确指定一个数据类型&#xff0c;并包含一个或多个变量的列表。例如&#xff1a; type variable_list; 在这里&#xff0c;"type"必须是一个合法的C数据类…

【phaser微信抖音小游戏开发002】hello world!

执行效果&#xff1a; 将以下代码文本内容&#xff0c;放入到game.js中即可。目录结构如下图 import ./js/libs/weapp-adapter import ./js/libs/symbolGameGlobal.window.scrollTo () > { };//防止真机出错 import Phaser from ./js/phaser//引入Phaservar {windowWidth, …

P2550 [AHOI2001] 彩票摇奖

题目描述 为了丰富人民群众的生活、支持某些社会公益事业&#xff0c;北塔市设置了一项彩票。该彩票的规则是&#xff1a; 每张彩票上印有 7 7 7 个各不相同的号码&#xff0c;且这些号码的取值范围为 1 ∼ 33 1\sim33 1∼33。每次在兑奖前都会公布一个由七个各不相同的号码…

eam资产管理系统,eam资产管理系统功能介绍

基于固定资产管理系统PDA并结合RFID技术固定资产管理信息系统将固定资产管理、低价值消耗品管理和设备维护融为一体。根据先进的射频识别技术&#xff0c;从资产购买公司到资产退出的整个生命周期&#xff0c;每一个固定资产唯一的条形码资产标签都被赋予了后续管理&#xff0c…
推荐文章