`set` from `initializeState` does not trigger hooks
See original GitHub issueWhen 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:
initializeState
being run first (“Init state”)- The first value read from
useRecoilValue
- this is the default value set
is called insideinitializeState
butuseRecoilValue
isn’t triggered again
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:
- Created 3 years ago
- Comments:7 (3 by maintainers)
Top 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 >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
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 asuseSetRecoilState()
oruseRecoilCallback()
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 akey
prop to<RecoilRoot>
to force re-mounting and re-initialization.