Recoil icon indicating copy to clipboard operation
Recoil copied to clipboard

Using hooks within selectors

Open grod220 opened this issue 3 years ago • 4 comments

At the moment, selectors do not allow for any hooks inside of it. This is unfortunate because most external libraries provide hooks. This means it's quite difficult to fully move your logic into recoil. You have to rely upon boilerplate patterns like creating custom hooks that sync the result of the hook with recoil atoms.

Here's an example of this common pattern: https://github.com/facebookexperimental/Recoil/issues/727#issuecomment-754456755

Anything on the roadmap related to this?

grod220 avatar Nov 04 '21 22:11 grod220

Yes, actually. The synchronization library we're working on has a pattern which helps with syncing atoms with values from hooks. See this example This particular example initializes with data from props, but data from hooks could be used as well as bi-directional syncing and subscriptions.

drarmstr avatar Nov 04 '21 22:11 drarmstr

Awesome to hear you are thinking about this! Just some feedback.

<SyncWithProps spam="SPAM" eggs="EGGS" />
<ReadsAtom atom={atomA} />

I find this pattern to be a bit odd as it moves state logic into a place where UI components are typically expected to be. For example, I think it would be nicer to have something like this:

const value = useRecoilValueAndSync(definedAtom, useCustomHook())

The best would be being able to use a hook within a selector, but I'd understand if there are inherent limitations with that.

grod220 avatar Nov 05 '21 12:11 grod220

The intent is to keep the atom-specific sync logic in one place with the atom definition, that's what described what we sync. It is then abstracted with how it is synced with a hook that acts as a bridge between the non-React atoms and React hooks. It shouldn't be interlaced with UI logic, that was just a trivial test example. Hopefully it will be more clear when we get documentation.

drarmstr avatar Nov 06 '21 01:11 drarmstr

Hi, I'm trying out Recoil in my project. I found it hard to set an atom state in an async selector, the case just be like:

export const useDataQuery = selector({
  key: 'useDataQuery',
  get: async ({ get }) => {
    const resp = await fetchData(Number(get(teamIDState)));
    return resp;
  },
});

I'm wondering how to set a loading state when the selector running the fetch function, and then I want to use useSetRecoilState but found we can't use the hook in the selector. Is there a way to do loading state update?

fyyhome avatar Jul 20 '22 07:07 fyyhome