Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can an atom's value be changed from a non-react environment? #546

Closed
Nishchit14 opened this issue Sep 2, 2020 · 5 comments
Closed

Can an atom's value be changed from a non-react environment? #546

Nishchit14 opened this issue Sep 2, 2020 · 5 comments
Assignees
Labels
question Further information is requested

Comments

@Nishchit14
Copy link

Nishchit14 commented Sep 2, 2020

Recently I came across the use case like a pure js file Realtime.service.js is making a connection with the WebSocket server and streaming realtime data to UI (need to feed multiple React's components with a chunk of data coming from realtime WS).

Now if Recoil's atom state can be changed directly from Realtime.service.js (which is not a React component but js service) with realtime steam then all the components connected with the relative atoms will be updated on realtime data streaming.

Is that a valid use case? Right now I've seen that Atom's state only get/set default-value by React's hook.

In redux it is possible, we can update the store from any js file (non-react env). and the react-redux bridge auto handles the changes to connected components. Now we're moving from Redux to Recoil, we're having this roadblock.

@kulkalkul
Copy link

kulkalkul commented Sep 2, 2020

It isn't possible to access them outside of React as stated in #5. But you can do something like this to sync them:
https://recoiljs.org/docs/guides/asynchronous-state-sync

I use this method to sync my state to leveldown DB in my electron application.

@ajoslin
Copy link

ajoslin commented Sep 2, 2020

You could hack it

function MyCmp () {
  const setValue = window.setValue = useSetRecoilState(someState)
}

function somewhereElse () {
  window.setValue(123)
}

@drarmstr drarmstr self-assigned this Sep 3, 2020
@BenjaBobs
Copy link

My team uses an empty component to capture and expose a getLoadable() and set() function. This only works if you have exactly one <RecoilRoot> though:

import React from 'react';
import {
    atom, AtomOptions, Loadable, RecoilState, RecoilValue, selector, Snapshot, useRecoilCallback,
    useRecoilSnapshot
} from 'recoil';

// internal variables to hold the relevant recoil objects
let __snapshot: Snapshot = null as any;
let __set: <T>(
  recoilVal: RecoilState<T>,
  valOrUpdater: ((currVal: T) => T) | T
) => void = null as any;

// expose a function to set recoil state
export function RecoilSet<T>(
  recoilVal: RecoilState<T>,
  valOrUpdater: ((currVal: T) => T) | T
) {
  __set(recoilVal, valOrUpdater);
}

// expose a function to get recoil state
export function RecoilGetLoadable<T>(recoilValue: RecoilValue<T>): Loadable<T> {
  return __snapshot.getLoadable(recoilValue);
}

// This component captures a snapshot to expose a get function, and a callback to expose a set function
export function RecoilUtilsComponent() {
  __snapshot = useRecoilSnapshot();

  useRecoilCallback(({ set }) => {
    __set = set;

    return async () => {};
  })();

  return <></>;
}

And this is our react root:

export default function Startup() {
  return (
    <RecoilRoot>
      {/* this component is empty and it's only purpose is to sync external state with Recoil */}
      <RecoilUtilsComponent />
      <HistoryRecoilSync />
      <MediaQueryRecoilSync />
      <Initialize>
        <AppHost />
      </Initialize>
    </RecoilRoot>
  );
}

It's handy when we want to set some auth data as part of authentication/login flow.

@drarmstr
Copy link
Contributor

drarmstr commented Sep 3, 2020

I'm hopeful that this API #380 could help with this use case.

@drarmstr
Copy link
Contributor

Updated documentation for syncing Recoil state with external storage in #680

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

5 participants