const fetchList = (): Promise<typeof LIST> =>
new Promise((resolve) => {
setTimeout(() => resolve(LIST), 100);
});
const fetchItem = (id: string) =>
new Promise((resolve) => {
setTimeout(() => resolve(LIST.find((item) => item.id === id)), 100);
});
const listAtom = atom({
key: "listAtom",
default: selector({
key: 'listAtom/Default',
get: async () => {
console.log('executed!');
return await fetchList()
}
})
});
const itemAtom = atomFamily({
key: "itemAtom",
default: selectorFamily({
key: "listAtom/Default",
get: (id: string) => async ({ get }) => {
const list = get(listAtom) || [];
if ("find" in list) {
const item = (list as any[]).find((d) => d.id === id);
if (item) {
return item;
}
}
return await fetchItem(id);
}
})
});
const Test = () => {
const data = useRecoilValueLoadable(itemAtom("1"));
return <>{data.state}</>;
};
then, executed! is logged
can i get listAtom's value or null without async call??
You can use noWait to get a loadable instead of waiting for a value: https://recoiljs.org/docs/api-reference/utils/noWait
Thanks again @BenjaBobs! Yes, noWait() is great for getting a Loadable object including the current state (hasValue, hasError or loading). You can also use the useRecoilValueLoadable() hook from a component. The advantage of noWait() is that it can also be used from a selector evaluation function.
no! i want no call async function! just get value if selector has. but noWait call async function.
no! i want no call async function! just get value if selector has. but
noWaitcall async function.
For that, you could set the default value of listAtom to null, then explicitly make your async call when you actually want to and then set the value of listAtom to the results when available.
hmm.. what about add skipAsync on noWait option, and get stored data from atom? if has not data then return null.
if i set listAtom to store data, then i will call async function on component. but i want set data on selector...