跳至主要内容

·阅读时间 1 分钟
  • 修复 useRecoilCallback() 中潜在的未处理承诺拒绝 (#2075)
  • 通过 RecoilEnv.RECOIL_GKS_ENABLEDGateKeeper 特性切换添加 OSS 支持 (#2078)
  • 修复使用 SSR 时异步选择器的悬念解析 (#2073, #1960)
  • 修复某些版本的 React DOM 与 Next.JS 13 一起使用时的 SSR (#2082, #2086)

·阅读时间 1 分钟
  • 公开标志以禁用“重复原子键”检查/日志记录,因为在 NextJS 或使用快速刷新的某些开发环境中它过于嘈杂。 (#733, #2020, #2046)

    • 从 recoil 包中导入 RecoilEnv,并在代码中设置 RecoilEnv.RECOIL_DUPLICATE_ATOM_KEY_CHECKING_ENABLED = false 以禁用检查和日志记录。
    • 我们还支持 NodeJS 环境中的 process.env.RECOIL_DUPLICATE_ATOM_KEY_CHECKING_ENABLED=false,例如 NextJs
    • 注意:这将禁用对重复原子键的所有检查,包括合法错误,因此请谨慎使用!
  • 针对使用不支持 useSyncExternalStore() 的嵌套渲染器的 React 18 环境的解决方法。 (#2001, #2010)

·阅读时间 1 分钟
  • 除了 updateItem()updateAllKnownItems() 之外,还为 listen 道具回调导出 updateItems()。 (#2017, #2035)
  • 当使用带有 param 的位置 queryParams 时,从 URL 中删除参数将重置原子。当原子可能与多个 URL 参数同步时,这将是一个轻微的破坏性更改。 (#1900, #1976)
  • 如果检测到 <RecoilURLSyncTransit> 的不稳定 handlers 道具,则会添加开发警告。 (#2044)

·阅读时间 1 分钟
  • boolean() 导出重命名为 bool(),因为 boolean 是一个保留字 (#1922, #1962, #1971)
  • package.json 中删除对 native 目录的引用,以清理 react-native 的错误。 (#1931)
  • 导出 Path 类以供自定义检查器使用。 (#1950, #1956)
  • 用每种类型扩展 union()or() 的失败消息。 (#1961)

·阅读时间 1 分钟
  • 修复开发期间 React 快速刷新的 useRecoilSnapshot() (#1891)
  • 修复从 Chrome v104 开始的浏览器行为更改后的 useRecoilSnapshot()recoil-sync (#1943, #1936)

·阅读时间 3 分钟

recoil-sync NPM 包的首次开源发布!Recoil 同步提供了一个附加库,以帮助将 Recoil 状态与外部系统同步。简单的 异步数据查询 可以通过选择器或 useEffect() 实现,或者 原子效果 可用于单个原子的双向同步。recoil-sync 附加包提供了一些额外的功能

  • 批处理原子事务 - 对多个原子的更新可以与外部系统一起作为单个事务进行批处理。如果需要原子事务才能获得相关原子的一致状态,这一点可能很重要。
  • 抽象且灵活 - 此 API 允许用户分别指定要同步的原子,而不是描述如何同步的机制。这允许组件在不更改其实现的情况下使用原子并与不同环境中的不同系统同步。例如,组件可以使用在独立工具中使用时会持久保存到 URL 的原子,而当嵌入到另一个工具中时会持久保存到自定义用户数据库中。
  • 验证和向后兼容性 - 当处理来自外部来源的状态时,验证输入非常重要。当状态在应用程序生命周期之外持久保存时,还需要考虑先前版本状态的向后兼容性。recoil-syncrefine 有助于提供此功能。
  • 原子到外部存储的复杂映射 - 原子与外部存储项之间可能不存在一对一映射。原子可能会迁移到使用更新版本的项,可能会从多个项中提取属性,只是某种复合状态的一部分,或者其他复杂映射。
  • 与 React Hook 或 Props 同步 - 此库允许将原子与从原子效果无法访问的 React Hook 或 Props 同步。

recoil-sync 库还为外部存储提供内置实现,例如 与浏览器 URL 同步


基本思路是,可以为希望同步的每个原子添加 syncEffect(),然后在你的 <RecoilRoot> 内添加一个 <RecoilSync> 来指定如何同步这些原子。你可以使用内置存储,例如 <RecoilURLSyncJSON>创建自己的存储,甚至将不同组的原子与不同的存储同步。

示例

URL 持久化

以下是一个简单的示例,说明如何 将原子与浏览器 URL 同步

const currentUserState = atom<number>({
key: 'CurrentUser',
default: 0,
effects: [
syncEffect({ refine: number() }),
],
});

然后,在应用程序的根目录处,只需包含 <RecoilURLSyncJSON>,即可将所有这些标记的原子与 URL 同步

function MyApp() {
return (
<RecoilRoot>
<RecoilURLSyncJSON location={{part: 'queryParams'}}>
...
</RecoilURLSyncJSON>
</RecoilRoot>
)
}

就是这样!现在这个原子将在初始加载时根据 URL 初始化其状态,任何状态变异都会更新 URL,而 URL 的更改(例如后退按钮)会更新原子。在 同步效果存储实现URL 持久化 指南中查看更多示例。

·阅读时间 2 分钟

用于 Flow 和 TypeScript 的类型细化和输入验证库 @recoiljs/refine 的首次开源发布!要开始学习有关精炼的知识,请查看有关 实用程序检查器 的核心概念的文档。

Recoil 同步 库利用 **精炼** 来进行类型细化、输入验证和升级类型以实现向后兼容性。有关更多详细信息,请参阅 recoil-sync 文档

为什么我要使用精炼?

  • 当你的代码遇到 unknown TypeScript 类型或 mixed Flow 类型值,并且你需要 断言这些值具有特定的静态类型 时,精炼很有用。
  • 精炼提供了一个 API 来构建类型细化辅助函数,这些函数可以验证未知值是否符合预期类型。
  • 精炼可以验证输入值,并 从先前版本升级

类型细化示例

将未知类型强制转换为强类型变量。如果输入不匹配预期类型,则 assertion() 会抛出异常,而 coercion() 会返回 null

const myObjectChecker = object({
numberProperty: number(),
stringProperty: optional(string()),
arrayProperty: array(number()),
});

const myObjectAssertion = assertion(myObjectChecker);
const myObject: CheckerReturnType<myObjectChecker> = myObjectAssertion({
numberProperty: 123,
stringProperty: 'hello',
arrayProperty: [1, 2, 3],
});

向后兼容示例

使用 match()asType(),你可以从先前类型升级到最新版本。

const myChecker: Checker<{str: string}> = match(
object({str: string()}),
asType(string(), str => ({str: str})),
asType(number(), num => ({str: String(num)})),
);

const obj1: {str: string} = coercion(myChecker({str: 'hello'}));
const obj2: {str: string} = coercion(myChecker('hello'));
const obj3: {str: string} = coercion(myChecker(123));

JSON 解析器示例

精炼包装了 JSON,以提供一个内置的强类型解析器。

const myParser = jsonParser(
array(object({num: number()}))
);

const result = myParser('[{"num": 1}, {"num": 2}]');

if (result != null) {
// we can now access values in num typesafe way
assert(result[0].num === 1);
} else {
// value failed to match parser spec
}

·阅读时间 1 分钟
  • 修复缺少的流类型 (#1857)
  • 清理使用带有选择器默认值的原子时的内存泄漏。 (#1821, #1840, #1844)

·阅读时间 1 分钟

使用 **GraphQL** 的库 recoil-relay 的首次开源发布!

该库帮助 Recoil 使用 GraphQLRelay 库执行类型安全且高效的查询。它提供了选择器,可以轻松地使用 GraphQL 查询。查询与 Recoil 数据流图同步,因此下游选择器可以从查询中派生状态,它们可以依赖于上游 Recoil 状态,并且它们会自动订阅来自 Relay 的图中的任何更改。一切都会自动保持同步。

示例

GraphQL 查询就像定义一个 GraphQL 选择器 一样简单

const userNameQuery = graphQLSelector({
key: 'UserName',
environment: myEnvironment,
query: graphql`
query UserQuery($id: ID!) {
user(id: $id) {
name
}
}
`,
variables: ({get}) => ({id: get(currentIDAtom)}),
mapResponse: data => data.user?.name,
});

然后像使用任何其他 Recoil 选择器 一样使用它

function MyComponent() {
const userName = useRecoilValue(userNameQuery);
return <span>{userName}</span>;
}

·阅读时间 1 分钟
  • 使原子和选择器能够在 家族参数 中使用 (#1740)
  • parentStoreID_UNSTABLE 添加到原子效果中,用于克隆原子实例的父 Recoil 存储。这使得 GraphQL 的预取模式 成为可能。(#1744)
  • 原子效果可以初始化或将原子设置为包装的值 (#1681)