Recoil: use useRecoilState inside selector get?

Created on 16 May 2020  ·  6Comments  ·  Source: facebookexperimental/Recoil

get and useRecoilState do very similar thing.
Not sure how realistic it would be to useRecoilState inside selector

const filteredTodoListState = selector({
    key: 'filteredTodoListState',
    get: ({get}) => {
        // const filter = useRecoilState(todoListFilterState)
        const filter = get(todoListFilterState);
        return filter;
    }
})

All 6 comments

Hi @alexandrzavalii

The Rules Of Hooks say that a hook can only be called from either React function components or as part of a custom hook. This means they can't be called inside a function like a Recoil selector.

Hi @acutmore , thanks for reply.
I know about this rule, but get function looks to me like a body of a custom hook, it will rerender if the value changes.

Agreed @alexandrzavalii they do look like the body of a custom hook.

The difference is when the function gets called. Hooks need to be called when React is 'rendering' a Function component. This is how React knows which part of the component tree 'owns' that hook.

The problem with putting the hook inside the selector is that Recoil (EDIT: an async selector ) may call the get function at a different point in time, after the component has rendered. This means that the hook calls inside the implementation of useRecoilState like useCallback will throw an exception.

@acutmore Cool thanks! I thought it has the same behavior as hooks, and “get” is always immediately called on render.
Thanks for explanation!

@alexandrzavalii You are correct, I was not very clear. The get function passed to the selector is called during render. Though that function could be async, so the internal get could be after the render.

const delayNumberState = selector({
  key: "delayNumberState",
  get: async ({ get }) => {
    const delay = get(delayState);
    await new Promise(resolve => setTimeout(resolve, delay));
    const number = get(numberState); // get called outside of React render
    return number;
  }
});

Even if calling the hook was safe in practice the rules-of-hooks eslint rule would not know that and would display an error/warning.

oh yeah, I definitely forgot about the async use-case. And also get does not have to be at the top level.
yeah there is no way you could use hooks in that case.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

polemius picture polemius  ·  3Comments

yuantongkang picture yuantongkang  ·  3Comments

Etherum7 picture Etherum7  ·  3Comments

jamiewinder picture jamiewinder  ·  3Comments

thegauravthakur picture thegauravthakur  ·  3Comments