How rehydration works?
josoroma-zz opened this issue · 8 comments
Hi hackers!
I was wondering... what is this the right way to rehydrate the state?
My current version is:
state/user/atom.ts
import { atom } from "recoil";
import StateUser from "state/user/types";
import { statePersist } from "config/constants";
const ATOM_KEY = "user";
const userDefault: StateUser = {
email: "",
firstName: "",
id: "0",
lastName: "",
token: "",
};
/**
* Get the localStorage persisted state, then rehydrate the atom.
*/
const userPersistedStorage = window.localStorage.getItem(statePersist.key);
const userPersisted = userPersistedStorage
? JSON.parse(userPersistedStorage)[ATOM_KEY]
: userDefault;
/**
* User State - Create or Rehydrate the Atom.
*/
const userAtom = atom({
key: ATOM_KEY,
default: userPersisted,
// @ts-ignore
persistence_UNSTABLE: {
type: ATOM_KEY,
},
});
export default userAtom;
index.tsx
import React, { StrictMode } from "react";
import ReactDOM from "react-dom";
import { RecoilRoot } from "recoil";
import recoilPersist from "recoil-persist";
import { statePersist } from "config/constants";
import "./index.css";
import App from "./App";
const { RecoilPersist, updateState } = recoilPersist(
statePersist.atomsToPersist,
{
key: statePersist.key,
storage: localStorage,
}
);
ReactDOM.render(
<StrictMode>
<RecoilRoot initializeState={updateState}>
<RecoilPersist />
<App />
</RecoilRoot>
</StrictMode>,
document.getElementById("root")
);
Do recoil-persist offers state rehydration?
@josoroma Hi, yes, recoil-persist offers state rehydration. But I am not sure what this lines are doing in your code?
const userPersistedStorage = window.localStorage.getItem(statePersist.key);
const userPersisted = userPersistedStorage
? JSON.parse(userPersistedStorage)[ATOM_KEY]
: userDefault;
recoil-persist should rehydrate the state.
The default value could be userDefault
.
Please take a look in examples in README.md
Thanks a bunch @polemius !
I tried: https://github.com/polemius/recoil-persist#usage
const { RecoilPersist, updateState } = recoilPersist(
statePersist.atomsToMantain, // ['user']
{
key: statePersist.key,
storage: localStorage
}
)
but this part is never rehydrating the user state (once I refresh the browser the localstorage data exist but the rehydration is being ignored):
<RecoilRoot initializeState={({set}) => {
updateState({set})
}>
<RecoilPersist />
<App />
</RecoilRoot>
Not sure what I am not doing right!
Thanks!
@polemius those lines are just getting the whole state from the localStorage, then it get the user slice only. So if the data exists in localStorage it will rehydrate this data on any browser reload, if not, it will use the default values. So to me, this hack is making the rehydration part work.
@josoroma This is strange that rehydration doesn't work. Try remove any properties from recoilPersist
function. Then it should store everything.
const { RecoilPersist, updateState } = recoilPersist()
<RecoilRoot initializeState={({set}) => updateState({set})>
<RecoilPersist />
<App />
</RecoilRoot>
Also try check the localstorage in your browser.
Are you updating the atom values? Because recoil-persist will save data only if the atom will change (limitation of recoil library).
Thanks for your time @polemius !
No luck from my side!
constants
https://github.com/lognllc/reacter/blob/master/src/config/constants.js#L1
recoilPersist
https://github.com/lognllc/reacter/blob/master/src/index.tsx#L18
How we made rehydration possible on every browser reload
https://github.com/lognllc/reacter/blob/master/src/state/user/atoms.ts#L21
Updating the atom values here:
https://github.com/lognllc/reacter/blob/master/src/screens/Login/index.tsx#L39
@josoroma I have ran your project locally and found that function set
from RecoilRoot
doesn't work to setting the value for your atom. If I am trying use set directly like this:
ReactDOM.render(
<StrictMode>
<RecoilRoot
initializeState={({ set }) => {
// set({ key: "user" }, { email: "test" });
updateState({ set });
}}
>
<RecoilPersist />
<App />
</RecoilRoot>
</StrictMode>,
document.getElementById("root")
);
I am getting error Error: Missing definition for RecoilValue: "user""
I have checked and looks like Recoil
doesn't see the atoms if it is not in app tree. You are using lazy loading for each module so user atom not in the app tree.
I have changed the App.tsx
to getting the value from atom:
const App: FC = () => {
const value = useRecoilValue(userAtom);
return (
<>
<CssBaseline />
<Routes history={history} />
</>
);
};
Also I set in user atom default value to default: userDefault
. To prevent loading from localstorage with your mechanism.
And suddenly everything works as expected.
I have created the PR with my changes. Please take a look: mismoteam/reacter#1
sweet!!! thank you @polemius
100%