自从Facebook将Recoil作为其React应用的新标准管理库介绍给世界以来,已经有一段时间了。尽管该库仍处于开源项目的实验旗帜下,但Recoil有前途的功能已经证明了它一个又一个版本的价值。
最近,Facebook接连发布了两个新版本,Recoil 0.2和Recoil 0.3。最近的更新引入了一堆错误修复和对整体开发体验的改进。在本指南中,我们将强调一些最重要的新功能。
如果想了解Recoil是如何工作的,请查看我们的Recoil介绍和创建CRUD应用程序的指南。
Recoil的Snapshot
如果你以前使用过Recoil,你会熟悉原子的概念。原子基本上是Recoil中的一块状态。它由一个atom() 函数表示,该函数返回一个RecoilState 对象,你可以向其写入数据。
因为我们主要使用React Hooks来处理所有事情,Recoil使你能够通过几个Hooks来处理原子,包括 [useRecoilState()](https://recoiljs.org/docs/api-reference/core/useRecoilState).
A Snapshot对象,顾名思义,是这些原子内状态的不可改变的快照。作为一个程序员,你不可能在你的日常生活中使用快照,因为状态在不断变化。然而,它对诸如状态同步、开发工具功能等方面非常有用。
在Recoil中,基本上有三种主要的方式来获取特定状态的快照。
- 通过
useRecoilCallback钩子,它允许异步访问到一个特定的状态。Snapshot - 通过
useRecoilSnapshot钩子,它允许同步访问一个对象。Snapshot - 通过
useRecoilTransactionObserver_UNSTABLE钩子,它允许在原子发生任何状态变化时订阅Snapshots。
Recoil 0.3为快照引入了一个轻微的突破性变化。现在,一个Snapshot 对象可能只活到回调或渲染过程结束。如果你目前的代码使用快照的时间超过这个时间,你会看到在开发者模式下,一些警告信息出现在你的控制台。然而,该团队正在开发一个新的API,名为retain() ,以使其使用的时间更长。在即将发布的版本中注意这个功能。
RecoilRoot'soverride
RecoilRoot必须永远是任何使用回收钩子的组件的祖先。它通常被添加到React应用的根组件中。然而,这取决于你,因为你的应用程序也可以共享多个RecoilRoot,代表原子状态的独立存储。
由于这种特殊性,Recoil保证每个原子对于它所属的每个根总是有自己的值。比如说。
const container = renderElements(
<RecoilRoot>
<ReadsAtom atom={myAtom} />
<RecoilRoot>
<ReadsAtom atom={myAtom} />
</RecoilRoot>
</RecoilRoot>
);
在这种情况下,对于嵌套的根的行为仍然是一样的,即内层的根掩盖了外层的根。为了防止这种情况,Recoil 0.3为RecoilRoot 引入了一个新的属性,叫做override 。
如果一个内部的RecoilRoot ,并将override 属性(默认为true )设置为false ,则不会对其祖先执行任何功能。
const container = renderElements(
<RecoilRoot>
<ReadsAtom atom={myAtom} />
<RecoilRoot override={false}>
<ReadsAtom atom={myAtom} />
</RecoilRoot>
</RecoilRoot>
);
现在,当你,例如,用override 到false. 卸载一个嵌套的根集时,也会有同样的行为。这个动作不会清理祖先的根原子。
新选择器的getCallback() 功能
一个Recoil选择器是一个无副作用的 "纯函数",它对一组依赖值返回相同的值。Recoil使用它们来确定状态变化何时发生,并通知订阅该特定选择器的组件,以便它能够正确地重新渲染。
选择器可以是只读的,也可以是可写的,这取决于提供的函数。如果你只提供一个get ,选择器会返回一个RecoilValueReadOnly 对象。如果有一个set ,它返回一个RecoilState 对象。
下面是一个简单的例子,说明如何用Recoil使用选择器。
const doubleSelector = selector({
key: 'DoubleSelector',
get: ({get}) => get(myAtom) * 2,
});
其逻辑是这样的:如果任何一个选择器的依赖关系得到更新,选择器就会重新评估其get 方法。在我们的例子中,如果myAtom 状态更新,get 方法也会更新,因为我们现在有一个新的双等式的值。很简单,不是吗?
然而,有时候,你可能想使用相同的选择器来返回其中有回调的对象。比方说,你有一个选择器,每当列表中的一个项目的ID更新时,就返回一个组件。选择器检测到这个变化并触发get 方法来重新计算显示项目相关信息的模态。
你可以通过Recoil 0.3中包含的新的getCallback() 函数轻松实现这一目标。
const heySelector = selector({
key: 'HeySelector',
get: itemID => ({get, getCallback}) => {
const onClick = getCallback(({snapshot}) => async () => {
const item = await snapshot.getPromise(queryForSomethingById(itemID));
showModal(item);
});
return {
title: `Hey, I'm a component!`,
onClick,
};
},
});
它与我们的useRecoilCallback() 非常相似。然而,getCallback() 函数更适用于你需要稍后访问状态的用例,例如当当前组件上下文之外的一些逻辑需要该对象执行特定操作时。
使用HAMT改善性能
Recoil 0.2引入了一个增强功能,大大改善了原子值克隆的速度。
今天,recoil使用内置的map数据结构来复制和设置原子值的映射,当一个写入发生时。这一变化引入了使用哈希数组映射的Trie(HAMT)实现,它处理关联数组,以结合哈希表和数组映射的Trie(搜索树)的能力。
这一变化使这种写入操作的速度提高了325倍,执行的条目数最多为1000个。有一万个条目的执行速度惊人地增加了3000倍。
你可以在GitHub上看一下新的实现。
结论
Recoil 0.2和0.3版本主要引入了基本和非突破性的变化。其中包括对原子族的时间和内存消耗的可扩展性的改进,在各种使用情况下更友好的错误抛出,对Safari的更好支持,以及更多。
当下一个主要版本发布时,你可能会期待一个更大的实质性变化清单,而且Recoil项目会从实验状态迁移到正式状态。
The postWhat's new in Recoil 0.3?appeared first onLogRocket Blog.