Recoil: Interacting with atoms from outside of React environment

Created on 8 Sep 2020  路  4Comments  路  Source: facebookexperimental/Recoil

Hi everyone. Thank you for creating this great library.

The problem of interacting with atoms' state from outside of React has already been told. Here is one similar closed issue, and one more open. But the problem is still actual, and I want to ask questions on which I couldn't find answers.

First, let me show a typical example which leads to the issue.

Let's imagine we have a simple React app generated with CRA. At the bottom of src/index.js of each CRA app, we have a service worker registration section. Here is an example (a little bit modified), where we interact with the store during SW registration.

Screen Shot 2020-09-08 at 15 50 24

Here, as a store/state management tool is used Overmindjs. Now, when we try to convert this logic into Recoil we face a problem; we can't use Recoil outside of the React environment.

  • we can register the service worker in a react component
  • we can catch and store (somewhere outside) the setter function with transaction observer (useRecoilTransactionObserver) or by rendering a React component (mentioned by @davidmccabe in this discussion)
  • we can use atom effects (mentioned by @drarmstr in this discussion); actually, I don't understand how atom effects are going to handle this case (the only way I see is catching and storing the setter function somewhere outside like in the prev version), so, I would ask @drarmstr to explain it if it's possible

For me, all of them look like workarounds. In my case, I used the second option. I created a custom hook, caught, and stored the setter function somewhere outside. It looks like this:

Screen Shot 2020-09-08 at 15 52 08

Screen Shot 2020-09-08 at 15 51 18

According to all of this, I have some questions:

  • Why it's not possible to interact with atoms from outside of React env? You mentioned that Recoil's provided graph is orthogonal to the React tree (if I understood correctly). So, at first glance, this definition makes Recoil's graph even more independent. I was wondering if there is a technical restriction to do that?
  • Do you have plans for this in the future? Recoil seems a very powerful tool, but to be able to handle the whole app state management, in my opinion, it's important to be able to work from outside of React env.
duplicate

Most helpful comment

Duplicate of #546

The Recoil data flow graph is distinct from the React component tree, however the state of the atoms is coupled with the React component tree state. This is actually a very important distinction with other state management libraries. Recoil is looking to the future by supporting React Concurrent Mode. In this world, there is no "global" state. React may render some components based on some state, pause, and asynchronously render other components based on different state. Thus, to manage this, and properly render everything in sync, it is important to couple and bind the Recoil state to the state of the React component tree being rendered. So, all Recoil state is derived from the React context.

All 4 comments

Duplicate of #546

The Recoil data flow graph is distinct from the React component tree, however the state of the atoms is coupled with the React component tree state. This is actually a very important distinction with other state management libraries. Recoil is looking to the future by supporting React Concurrent Mode. In this world, there is no "global" state. React may render some components based on some state, pause, and asynchronously render other components based on different state. Thus, to manage this, and properly render everything in sync, it is important to couple and bind the Recoil state to the state of the React component tree being rendered. So, all Recoil state is derived from the React context.

Thank you for your reply @drarmstr. I understood the theoretical part. One more question: is the solution described above considered a normal one? I mean, can we use such kind of workarounds in such cases or there are more proper ways?

You can save the setter callbacks to use them asynchronously. But, they only affect the state for the <RecoilRoot> they are associated with. The Atom Effects approach is safer in this regard because it can setup state synchronization whenever an atom is dynamically used with a <RecoilRoot>.

Thank you @drarmstr.

The idea of effects is a great and important (I would say unavoidable) feature. It solves lots of problems.
There are still some questions about this topic, but overall I got the idea and I can close the issue

Was this page helpful?
0 / 5 - 0 ratings