Recoil icon indicating copy to clipboard operation
Recoil copied to clipboard

Updater form of setters throw when current value is loading or in an error state.

Open wojtekmaj opened this issue 3 years ago • 3 comments

I have selector that asynchronously loads data and atom that uses it as its default value:


export const asyncDefaultAccounts = selector({
  key: 'asyncAccountsState',
  async get() {
    const response = await get('/api/accounts');
    return response;
  };
});

export const accountsState = atom({
  key: 'accountsState',
  default: asyncDefaultAccounts,
});

So far, so good. Works flawlessly.

But I also have a form that adds account and, on success, appends newly created account to the list:

const setAccounts = useSetRecoilState(accountsState);

function onSubmit() {
  const response = await post('/api/accounts', body);

  setAccounts((oldAccounts) => [
    ... oldAccounts,
    response,
  ]);
}

This forks good enough. UNLESS... I've never been to account list page and consequently have never subscribed to accountsState. In such case, the following error appears:

Tried to set the value of Recoil selector accountsState__withFallback using an updater function, but it is an async selector in a pending or error state; this is not supported.

An obvious fix would be to subscribe to Recoil state:

-const setAccounts = useSetRecoilState(accountsState);
+const [accounts, setAccounts] = useRecoilState(accountsState);

but this causes unnecessary GET from /api/accounts. Is there a way I could tell Recoil to set Recoil state, but only if said state has already been fetched, without subscribing to it?

wojtekmaj avatar Jul 05 '20 18:07 wojtekmaj

Yeah, we're currently discussing the semantics of asynchronous atom states and how to manage the updater form. Considering API tradeoffs now...

drarmstr avatar Jul 06 '20 23:07 drarmstr

Related to #237, #762

drarmstr avatar Aug 31 '20 23:08 drarmstr

any updates?

jh0l avatar Jan 31 '24 10:01 jh0l