Reputation: 41
Problem
After user login user details are saved in mobx state. but after page refresh those data are gone. I want to persist data on mobx state so the user data are stay on mobx state until user logout.
I tried mobx-persist-store but when I go to another page those data are gone again. How can I implement persistence store with or without mobx-persist-store in Next.js?
root-store-provider
import { createContext, FC, useContext } from "react";
import { RootStore } from "./root";
const RootStoreContext = createContext<RootStore>(new RootStore());
export const useStore = () => {
const context = useContext(RootStoreContext);
if (context === undefined) {
throw new Error("useStore must be used within StoreProvider");
}
return context;
};
let rootStore: RootStore | undefined;
const initializeStore = (initialData?: RootStore) => {
const _rootStore = rootStore ?? new RootStore();
if (initialData) {
_rootStore.hydrate(initialData);
}
if (typeof window === "undefined") return _rootStore;
if (!rootStore) rootStore = _rootStore;
return _rootStore;
};
interface Props {
children: React.ReactNode;
intialState?: RootStore;
}
export const RootStoreProvider: FC<Props> = ({ children, intialState }) => {
const store = initializeStore(intialState);
return (
<RootStoreContext.Provider value={store}>
{children}
</RootStoreContext.Provider>
);
};
rootStore
import { UserStore } from "./user";
import { hydrateStore, makePersistable } from "mobx-persist-store";
import localforage from "localforage";
export class RootStore {
user: UserStore;
constructor() {
this.user = new UserStore(this);
makePersistable(
this.user,
{
name: "RootStore",
properties: ["details", "cart"],
storage: typeof window !== "undefined" ? localforage : undefined,
},
{ delay: 200, fireImmediately: false }
);
}
async hydrate(data: RootStore): Promise<void> {
await hydrateStore(data);
}
}
Upvotes: 4
Views: 1592
Reputation: 7230
I got to make it work without localforage
package. Another thing I noted in your implementation is the use of makePersistable()
in RootStore
. It should be in your UserStore
, like in my example below:
import { makeObservable, observable, action } from "mobx"
import { makePersistable } from 'mobx-persist-store';
export class UserStore {
id: string = ""
email: string = ""
firstName: string = ""
lastName: string = ""
phone: string = ""
loggedIn: boolean = false
registrationComplete: boolean = false
constructor(initialData: any = {}) {
makeObservable(this, {
id: observable,
email: observable,
firstName: observable,
lastName: observable,
phone: observable,
loggedIn: observable,
registrationComplete: observable,
setEmail: action,
setFirstName: action,
setLastName: action,
setPhone: action
})
makePersistable(this, {
name: 'UserStore',
storage: typeof window !== "undefined" ? window.localStorage : undefined,
properties: [
'id',
'email',
'firstName',
'lastName',
'phone',
'loggedIn',
'registrationComplete'
]
})
this.id = initialData.id
this.email = initialData.email
this.firstName = initialData.firstName
this.lastName = initialData.lastName
this.loggedIn = initialData.loggedIn
this.registrationComplete = initialData.registrationComplete
}
setId(id: string) {
this.id = id
}
setEmail(email: string) {
this.email = email
}
setFirstName(firstName: string) {
this.firstName = firstName
}
setLastName(lastName: string) {
this.lastName = lastName
}
setPhone(phone: string) {
this.phone = phone
}
setLoggedIn(loggedIn: boolean) {
this.loggedIn = loggedIn
}
setRegistrationComplete(registrationComplete: boolean) {
this.registrationComplete = registrationComplete
}
logout() {
this.id = ""
this.email = ""
this.firstName = ""
this.lastName = ""
this.phone = ""
this.loggedIn = false
this.registrationComplete = false
}
__data() {
return {
id: this.id,
email: this.email,
firstName: this.firstName,
lastName: this.lastName,
phone: this.phone,
loggedIn: this.loggedIn,
registrationComplete: this.registrationComplete
}
}
}
Upvotes: 0