-
-
Notifications
You must be signed in to change notification settings - Fork 589
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Discussion: Provide jotai/nextjs utils #340
Comments
We have something like initialData in react-query, which works in Provider; I think we update it to work with provider-less mode. I think we can put it in 1-useAtom(atom, InitialData) or 2-atom.initialData, I think I prefer the first option. 1- const [data, setData] = useAtom(atom, initialData)
2- atom.initialData = {} |
I would agree, I think there is a lot of room for improvement and I bet it could be such that ssr can work kind of just out of the box, eg I define an atom that has an ability to fetch its own state, and it just works with loading the initial data out of the box. |
I was thinking along the same lines @aulneau, but I didn't want to come with any solutions, as this should be a discussion. |
Btw, I'm happy to work on any ideas that comes out of this. |
Let's do more discussions on that with @dai-shi and other folks; then, we'll work on it. Thanks for the issue! |
For sure :~) I don't mean to imply any correct solutions, and would be happy to help out too! |
I believe a great place to start would be Are there other use cases I'm not thinking of? |
Thanks for opening this issue up @Thisen .
I'm pretty sure there would be something to provide, but instead of thinking what is the thing, we would like to work on the best practices (especially because I'm not super familiar with next, yet). So the steps are:
|
@Aslemammad well, think it like the provider is left for use cases such as nextjs. we don't need to support provider-less mode and it's probably impossible. See the related discussion in zustand for example. Besides, changing the core api is the least thing we'd like to do. Keep it minimalistic. Let's do things on top of the core. |
Keeping the |
jotai/nextjs would be very specific to nextjs depending on functions from nextjs. If there were any generic SSR utils, we should put them in jotai/utils. |
So I'm working on a semi large site and we are using the current philosophy which seems to work for us. Would appreciate thoughts on this:
// _app.tsx
import { JotaiNextProvider } from "app/JotaiNextProvider";
const App = ({ Component, pageProps }) => (
<JotaiProvider pageProps={pageProps}>
<Component {...pageProps} />
</JotaiProvider>
);
export default App; This provider is custom, it wraps the Jotai Provider and sets initial state to an atom ( // JotaiNextProvider.tsx
import { Provider } from "jotai";
import { useEffect } from "react";
import { useUpdateAtom } from "jotai/utils";
import { appPropsAtom } from "app/appAtoms";
const JotaiContainer = ({ pageProps, children }) => {
const setInitialProps = useUpdateAtom(appPropsAtom);
useEffect(() => {
setInitialProps(pageProps);
}, [pageProps]);
return <>{children}</>;
};
const JotaiNextProvider = ({ pageProps, children }) => (
<Provider initialValues={[[appPropsAtom, pageProps]]}>
<JotaiContainer pageProps={pageProps}>{children}</JotaiContainer>
</Provider>
);
export { JotaiNextProvider }; Top level atom and derived atom // appAtoms.tsx
import { atom } from "jotai";
// We can just derive atoms from this
const appPropsAtom = atom({});
// Derived atoms
const apiContentAtom = atom((get) => get(appPropsAtom)?.apiContent);
const otherApiContentAtom = atom((get) => get(appPropsAtom)?.otherApiContent);
export { appPropsAtom, apiContentAtom, otherApiContentAtom }; Wherever we need SSR content we pass it into the top level atom and the use it in the page or any components without having to prop drill // pages/index.tsx
import { useAtomValue } from "jotai/utils";
import { apiContentAtom } from "appAtoms";
// Works for the other SSR functions as well
export async function getStaticProps() {
const apiContent = await fetchFromApi();
return { props: { apiContent } };
}
export default function IndexPage() {
// Read the atom and it will have the correct data when SSR
const apiContent = useAtomValue(apiContentAtom);
return <div>SSR content: {apiContent}</div>;
} |
@dai-shi AFAIK, props will be there on initial render. |
Yes it's to update the props, which are present on initial render and are also updated when navigating client-side. |
So looking at #637, am I right in saying that The above implementation could be rewritten as: // _app.tsx
const App = ({ Component, pageProps }) => {
useHydrateAtoms([[appPropsAtom, pageProps]]);
const setAppProps = useUpdateAtom(appPropsAtom);
useEffect(() => {
setAppProps(pageProps);
}, [pageProps]);
return <Component {...pageProps} />;
}; |
Yes, that's the idea. |
Hi everyone, there's a new hook |
As |
hi guys, can u give me an example of how to use |
Hi @sondh0127 👋🏼 - I'm assuming it's the |
|
That's the second argument of const idAtom = atom(1)
const userAtom = atomWithQuery((get) => ({
queryKey: ['users', get(idAtom)],
queryFn: async ({ queryKey: [, id] }) => {
const res = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`)
return res.json()
},
}), queryClient) |
Thank @Thisen. I've gotten the final code to work. Sharing it here in case someone is looking for it.
_app.tsx export const queryClientAtom = atom(new QueryClient())
function MyApp({ Component, pageProps }: AppPropsWithLayout) {
const [queryClient] = useAtom(queryClientAtom)
return (
<QueryClientProvider client={queryClient}>
<Hydrate state={pageProps.dehydratedState}>
...
</Hydrate>
</QueryClientProvider>
)
} state.tsx const idAtom = atom(1)
const userAtom = atomWithQuery(
(get) => ({
queryKey: ['users', get(idAtom)],
queryFn: async ({ queryKey: [, id] }) => {
const res = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`)
return res.json()
},
}),
(get) => get(queryClientAtom)
)
const User = () => {
const [user] = useAtom(userAtom)
return (
<div>
<i>
{user.name} | @{user.username}
</i>
<br />
<i>{user.phone}</i>
<br />
</div>
)
}
const StatePage: NextPageWithLayout = ({}) => {
return (
<>
<Provider>
<Suspense fallback="Loading...">
<User />
</Suspense>
</Provider>
</>
)
} |
We already provide some examples about how to use Jotai with Next.js and SSR in general.
This issue looks to start a discussion if it's possible for Jotai for provide a better story for using Jotai in a SSR scenario - We believe we could start with Next.js.
I believe this would be mostly useful in the scenario, where you have async atoms, which fetch their state using e.g.
fetch
.This is mostly inspired Next.js story for react-query: https://react-query.tanstack.com/guides/ssr
Let me think what you think - Should we provide something, or should we just document how to with our current API for "hydration" of atoms.
The text was updated successfully, but these errors were encountered: