question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

`set` from `initializeState` does not trigger hooks

See original GitHub issue

When reinitializing state using initializeState on RecoilRoot it appears that calling set does not trigger hooks, so my app is not updated.

In the image below you can see:

  1. initializeState being run first (“Init state”)
  2. The first value read from useRecoilValue - this is the default value
  3. set is called inside initializeState but useRecoilValue isn’t triggered again
Screenshot 2020-06-26 at 11 48 22

I’m using Recoil with React Native based on #114 - perhaps this is related to that?

This is the code I use to persist my atoms:

export default function createRecoilPersistor(
  atoms: Array<RecoilState<any>>
): Persistors {
  function initializeState({ set }: Initializer): void {
    console.log('Init state');
    for (const currentAtom of atoms) {
      const { key } = currentAtom;
      AsyncStorage.getItem(key).then(value => {
        if (value !== null) {
          console.log('Set value for ' + currentAtom.key, { value });
          set(currentAtom, JSON.parse(value));
        }
      });
    }
  }

  function RecoilPersistor(): null {
    useTransactionObservation_UNSTABLE(
      ({ atomValues, modifiedAtoms }: Observation): void => {
        for (const modifiedAtom of modifiedAtoms) {
          const matchingAtom = atoms.find(({ key }) => key === modifiedAtom);
          if (matchingAtom) {
            AsyncStorage.setItem(
              modifiedAtom,
              JSON.stringify(atomValues.get(modifiedAtom))
            );
          }
        }
      }
    );
    return null;
  }

  return {
    initializeState,
    RecoilPersistor
  };
}

Then in my App.js:

const { RecoilPersistor, initializeState } = createRecoilPersistor([
  darkModeAtom,
  userAuthAtom,
  userDetailsAtom
]);

function useTheme() {
  const darkMode = useRecoilValue(darkModeAtom);
  console.log({ initDarkMode: darkMode });
  const baseTheme = darkMode ? eva.dark : eva.light;
  const statusBarStyle = darkMode ? 'light-content' : 'default';
  return [{ ...baseTheme, ...customTheme }, statusBarStyle];
}

function App(): React.ReactElement {
  const [theme, statusBarStyle] = useTheme();
  return (
    <ApplicationProvider {...eva} theme={theme}>
      <StatusBar barStyle={statusBarStyle} />
      <NavigationRoot />
    </ApplicationProvider>
  );
}

export default function AppRoot(): React.ReactElement {
  return (
    <>
      <IconRegistry icons={EvaIconsPack} />
      <SafeAreaProvider>
        <RecoilRoot initializeState={initializeState}>
          <RecoilPersistor />
          <App />
        </RecoilRoot>
      </SafeAreaProvider>
    </>
  );
}

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:7 (3 by maintainers)

github_iconTop GitHub Comments

4reactions
drarmstrcommented, Jun 26, 2020

The initializeState prop is only intended to setup the initial state before the initial render. This is useful for supporting things like server-side rendering where it is critical the state is hydrated for that initial render. It is not intended for async updates to state. Use the existing Recoil hooks for updating state asynchronously, such as useSetRecoilState() or useRecoilCallback()

0reactions
drarmstrcommented, Apr 15, 2022

initializeState will only initialize on first mounting. Otherwise if the host component were ever re-rendered for any reason the state would unexpectedly be re-initialized. You can add a key prop to <RecoilRoot> to force re-mounting and re-initialization.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Why doesn't useState function initialize state every time?
So useState is a hook which helps you to handle state in a functional component. How is it working? Once you call useState...
Read more >
Simplifying state initializers with React Hooks - LogRocket Blog
What does it mean to initialize state? Generally speaking, to initialize means to set the value of something. Going by this definition, the ......
Read more >
The useState hook for setting state on an array of children
I'm not using the isEditing property yet… but soon. Initialize state in React app. In the component we're using to control our state,...
Read more >
useHooks - Easy to understand React Hook recipes
We bring you easy to understand React Hook code recipes so you can learn how React hooks work and feel more comfortable writing...
Read more >
4 Examples of the useState Hook - Dave Ceddia
It's not magic, but it relies on a truth you may not have thought about: React itself is calling your component, so it...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found