In my apps my store is usually the main abstraction layer that sits between the app and the API. By ensuring my React tree only references store methods when making API calls, I have a clear separation of concerns and am able to edit API related code confidently.
I am having trouble making this paradigm work with server components.
I am defining the store like so:
"use client";
...
const Context = createContext<Store | undefined>(undefined);
export default function AppProvider({ session, children }) {
const storeInstance = useMemo(() => createStore(session), []);
return (
<Context.Provider value={storeInstance}>
{children}
</Context.Provider>
);
}
export const useApp = () => useContext(Context);
In client components I can call useApp
to have access to my store and its state/methods.
However, I cannot do that in server components, as that would require importing and calling useApp
from a server component.
My root layout looks like this:
export default async function RootLayout({ children }) {
const client = createDatabaseAndAuthClient()
return (
<AppProvider session={await getSession(client)}>
...
</AppProvider>
);
}
This works for client components but I cannot figure out a way of giving server components access to the store when it's instantiated on the server. My attempts at defining it as a singleton export have failed.
How can I feed it through to server components, so that I can do something like:
import { store } from "@/lib/store";
export default async function Home() {
const user = await store.getUser();
return (
<>Hello from the server, {user.name}!</>
);
}
or perhaps there is a different way altogether? Advice appreciated.