我正在尝试创建一个动态表单,其中表单输入字段是根据 API 返回的数据呈现的。
由于atom需要有一个唯一的键,我尝试将它包装在一个函数中,但是每次我更新字段值或重新安装组件(尝试更改选项卡)时,我都会收到一条警告:
我在这里做了一个小的运行示例https://codesandbox.io/s/zealous-night-e0h4jt?file=/src/App.tsx(代码如下):
import React, { useEffect, useState } from "react";
import { atom, RecoilRoot, useRecoilState } from "recoil";
import "./styles.css";
const textState = (key: string, defaultValue: string = "") =>
atom({
key,
default: defaultValue
});
const TextInput = ({ id, defaultValue }: any) => {
const [text, setText] = useRecoilState(textState(id, defaultValue));
const onChange = (event: any) => {
setText(event.target.value);
};
useEffect(() => {
return () => console.log("TextInput unmount");
}, []);
return (
<div>
<input type="text" …Run Code Online (Sandbox Code Playgroud) 在 RecoilJS 中,与异步选择器的 React Suspense 无缝集成是一个很大的优势。然而,我在尝试标准化 Recoil 中缓存的数据时遇到了问题,同时仍然使用 Suspense。
为了通过示例解释该问题,用户可能有一组书籍。查询通过单个 API 调用填充集合,以获取所有用户的“最喜欢的”书籍。稍后的查询可能只请求一本书籍,该书可能已经或可能尚未通过最喜欢的书籍查询检索到。
我想要做的就是维护图书的规范化缓存,例如在由 bookId 键控的 AtomFamily 中,这样我就不会拥有使用不同查询提取的两本图书副本。但是,我遇到了一个问题,即我想对检索一本或多本书的任何一个查询使用 Suspense。使用 Recoil 来实现这一点的自然方法是使用异步选择器。但我不认为是否有一种方法可以标准化通过异步选择器获取的数据。
是否存在我忽略的模式,它允许我使用代表由共享的标准化 AtomFamily 支持的不同查询的异步选择器?
例如,如果我有这个 BAD 代码,它在我的状态中创建了重复的对象,那么我如何重新编写它以维护实际 Book 对象的共享缓存,并且如果当某个组件仍在获取查询时仍然使用 Suspense使用这个状态渲染?
查询1:通过选择器获取一组书籍:
const favoriteBooksSelector = selector({
key: 'MyFavoriteBooks',
get: async ({ get }) => {
const response = await allMyFavorityBooksDBQuery({
userID: get(currentUserIDState)
});
return response.books;
},
});
Run Code Online (Sandbox Code Playgroud)
查询 2:获取一本书,看起来像:
export const singleBookSelector = selectorFamily({
key: 'singleBookSelector',
get: (bookId: string) => async ({ get }) => {
const response = await singleBookDBQuery({
userID: …Run Code Online (Sandbox Code Playgroud)