我正在尝试将RecoilJS中原子的默认值设置为异步API调用的值。我这样做是为了在某个React组件渲染时,它将在数据库中拥有所有当前集,而不必调用useEffect()。这是我的密码。。。
const sets = (async () => await setService.getAll())()
export const setsState = atom({
key: 'sets',
default: sets
})
这是我得到的错误。。。
index.js:1 Warning: Cannot update a component (`Batcher`) while rendering a different component (`App`). To locate the bad setState() call inside `App`, follow the stack trace as described in https://facebook.com/setstate-in-render
in App (at src/index.js:10)
in Router (created by BrowserRouter)
in BrowserRouter (at src/index.js:9)
in RecoilRoot (at src/index.js:8)
我所采取的方法是否存在根本性的错误?我应该用另一种方式来完成吗?是我做错了什么,还是这只是Recoil的一个坏功能?
您可以尝试创建一个异步选择器,并将其放入atom的默认值中,如下所示:
const mySelector = selector({
key: 'mySelector',
get: async ({get}) => {
return await setService.getAll()
}
})
const myAtom = atom({
key:'myAtom',
default: mySelector
})
下面是一个Typescript示例,灵感来自这个答案。
// Inside your React component
const val = useRecoilValue(myAtom);
const updateVal = useSetRecoilState(mySelector);
// Update data with API call on form submit, and append new data to atom state
const onFormSubmit: SubmitHandler<DataFormValues> = async (values) => {
const createdData = await createDataWithApiCall();
await updateData([createdData]);
};
// Inside recoil state file
export const mySelector = selector({
key: 'mySelector',
get: async (): Promise<Array<Data>> => {
// Set default value to API result
const apiData = await callApi();
return apiData;
},
set: ({ set, get }, newData) => {
// Update state w/ new appended values
const currentState = get(myAtom);
const newState = [...currentState, ...newData as Data[]];
set(myAtom, newState);
},
});
export const myAtom = atom({
key: "myAtom",
default: mySelector,
});
上下文:每次用户向待办事项列表添加项目时,不需要从API重新绘制整个待办事项列表。调用API添加新项目,并将新项目附加到反冲状态。当用户想要进行编辑时也很有用。
Recoil维护人员知道您报告的警告,它将在下一个版本中修复。
不建议:如果你想暂时隐藏它,你可以将React降级为v16.12.0
,这取决于你是否能忍受这个警告,直到下一次Recoil发布