use react context in next project?
Unanswered
Cuvier’s Dwarf Caiman posted this in #help-forum
Cuvier’s Dwarf CaimanOP
is it wise to use react context in a next application?
I doubt that, because apps rely on server components.
What should I use to manage current user?
I doubt that, because apps rely on server components.
What should I use to manage current user?
41 Replies
Egyptian Mau
I have the same question!
I need to somehow update the state through certain scroll event listeners when my scroll is at a certain point and also update the same state from other components. What's the best way to do this?
I need to somehow update the state through certain scroll event listeners when my scroll is at a certain point and also update the same state from other components. What's the best way to do this?
I'm guessing using a useContext and wrapping the server components with a client side context provider would make everything be clientside?
Little yellow ant
For me it comes down to what the child components are doing with that data. Are they going to end up needing client side interaction anyways?
Brown bear
As you seem to know already, context only works in client components. However, nextjs apps will include client components for things that need client-side functionality. So, yes, you will end up using context where it makes sense: transient, client-sided context that needs to be shared among some components.
This could be a form, where you want to do some validation on the client before sending to the server, or a graph component where the user needs to be able to change some viewing options but they are not presisted server side, etc.
React contexts have their place in Nextjs apps. You just need to understand when they would be used: client side deeply nested context.
This could be a form, where you want to do some validation on the client before sending to the server, or a graph component where the user needs to be able to change some viewing options but they are not presisted server side, etc.
React contexts have their place in Nextjs apps. You just need to understand when they would be used: client side deeply nested context.
Brown bear
These client contexts can be global as well. You just cannot create and consume contexts from within server components. So, as an example, you could create a context providing client component, import it in your root layout, wrap the entire app in it, and then consume the context in deeply nested client components.
MyContext.jsx
"use client"
import { createContext } from "react"
const MyContext = createContext();
export const useMyContext = useContext(MyContext);
export function MyContextProvider({value, children}) {
return (
<MyContext.Provider value={value}>
{children}
</MyContext.Provider>
)
}
_layout.jsx
export default async function AppLayout() {
const value = await computeContextValueOnServer();
return (
<MyContextProvider value={value}>
{/* Rest of component tree, client or server components */}
</MyContextProvider>
)
}
MyClientComponent.jsx
"use client"
/* Imagine this component rendered deeply nested in the tree */
export function MyClientComponent() {
const myValue = useMyContext();
/* ... the rest of the component ... */
}
This usage pattern is explained here: https://nextjs.org/docs/app/building-your-application/rendering/composition-patterns#using-context-providers
@Egyptian Mau I'm guessing using a useContext and wrapping the server components with a client side context provider would make everything be clientside?
Brown bear
Doing this will not make everything client side. It's a common misconception that client components are ONLY rendered on the client. It just indicates that they have some client-driven functionality. They will still be rendered on the server, and then hydrated on client.
See the first line on this page
Client Components allow you to write interactive UI that is prerendered on the server and can use client JavaScript to run in the browser.https://nextjs.org/docs/app/building-your-application/rendering/client-components
Egyptian Mau
Thank you so much for the detailed response! This makes much more sense now @Brown bear
Sloth bear
It depends for what are you using the React context... to share data across multiple client component? Yes, is a good idea. To prevent prop drilling? No.
Egyptian Mau
what would be the perferred method than to prevent prop drilling?
As many say, is nothing wrong using prop drilling on server-side.
If you think that having too many props is 'ugly', you can group them under some objects.
Flemish Giant
Using React Context in a Next.js application can work, but it’s not always the best approach, especially because Next.js heavily relies on server components. With server-side rendering (SSR) and static generation, the state managed by React Context might not sync well between the server and the client, and React Context is purely client-side.
For managing the current user, I’d recommend handling authentication and user data on the server. One of the best tools for this in Next.js is NextAuth.js. It simplifies authentication, handles sessions, and integrates seamlessly with both server-side and client-side rendering. Alternatively, you could use React Query or SWR to fetch user data from the server and then store it in a global state, like Redux or Zustand, for client-side use.
So, instead of relying solely on React Context, it’s better to manage the user state through server-side authentication and then sync it with client-side state as needed.
For managing the current user, I’d recommend handling authentication and user data on the server. One of the best tools for this in Next.js is NextAuth.js. It simplifies authentication, handles sessions, and integrates seamlessly with both server-side and client-side rendering. Alternatively, you could use React Query or SWR to fetch user data from the server and then store it in a global state, like Redux or Zustand, for client-side use.
So, instead of relying solely on React Context, it’s better to manage the user state through server-side authentication and then sync it with client-side state as needed.
@Egyptian Mau What about situations where you need to share state data across multiple components?
Sloth bear
Prop drilling. You can eventually combine useContext (to access on client-side) and prop drilling for server components.
@Sloth bear Prop drilling. You can eventually combine useContext (to access on client-side) and prop drilling for server components.
Flemish Giant
yeah, this can work...but here is my opnion, this approach can quickly become unwieldy in larger applications or when the component tree gets deeply nested, as it tightly couples the data flow to the component hierarchy. what do u think about this?
@Flemish Giant yeah, this can work...but here is my opnion, this approach can quickly become unwieldy in larger applications or when the component tree gets deeply nested, as it tightly couples the data flow to the component hierarchy. what do u think about this?
Sloth bear
The purpose of Next.js is to reduce the client-side and do as much as possible on server-side (read the docs). Therefore, it is recommended to stick the data to server-side. You can always organize server component props into objects. Also you can write helpers to help you organize these components.
PayloadCMS managed to do this (you can check their repo).
@Sloth bear The purpose of Next.js is to reduce the client-side and do as much as possible on server-side (read the docs). Therefore, it is recommended to stick the data to server-side. You can always organize server component props into objects. Also you can write helpers to help you organize these components.
Flemish Giant
you're absolutely right, it shows the main differences between Next.js and React but i think this approach might not scale well.
For complex or frequently updated state, managing it on the server (for instance, via APIs) and then fetching it using a client-side library like React Query or SWR is often cleaner and more scalable.
while useContext works well for sharing client-side state across components, it has limitations. if the state changes frequently, every consuming component will re-render, potentially causing performance issues. in such cases, using a global state management library like Zustand or Redux provides better performance with fine-grained control over state updates. what do u think about this?
For complex or frequently updated state, managing it on the server (for instance, via APIs) and then fetching it using a client-side library like React Query or SWR is often cleaner and more scalable.
while useContext works well for sharing client-side state across components, it has limitations. if the state changes frequently, every consuming component will re-render, potentially causing performance issues. in such cases, using a global state management library like Zustand or Redux provides better performance with fine-grained control over state updates. what do u think about this?
@Flemish Giant you're absolutely right, it shows the main differences between Next.js and React but i think this approach might not scale well.
For complex or frequently updated state, managing it on the server (for instance, via APIs) and then fetching it using a client-side library like React Query or SWR is often cleaner and more scalable.
while useContext works well for sharing client-side state across components, it has limitations. if the state changes frequently, every consuming component will re-render, potentially causing performance issues. in such cases, using a global state management library like Zustand or Redux provides better performance with fine-grained control over state updates. what do u think about this?
Sloth bear
Well, I can't give a answer to a complex problem that I don't know at all. Yes, I know that complex applications doesn't scale so well, but that's why we're using Software Design Patterns, to be able to solve these problems.
I think, instead of looking to Reactish way of solving this problem, we should also look to Software Design Patterns and try to keep with Next.js way-of-doing-things.
Again, PayloadCMS (using Next.js as fundation) is also a complex application and does a lot server-side. They're grouping everything under deep objects.
Brown bear
@Sloth bear I think server sided prop-drilling and client sided context both have their use cases, and should be used where appropriate. For example, PayloadCMS uses tons of global/root level context providers for their admin:
- [RootLayout](https://github.com/payloadcms/payload/blob/main/packages/next/src/layouts/Root/index.tsx) is rendered on the server and is the root-level layout for the admin app. It is a server component, and wraps the entire app in:
- [RootProvider](https://github.com/payloadcms/payload/blob/main/packages/ui/src/providers/Root/index.tsx) which is a client component, having 16 context providers by my count.
I think there's confusion/fear of using client components in general, that they somehow poison the speed and savings you get from nextjs. There is no intrinsic harm in using them as long as you are separating the provider into a client component and not unnecessarily marking something with "use client" that could otherwise be a server component (i.e, your context providers should live in client components, and should be imported into server components).
When you do this appropriately, and don't have mismatches/hydration errors due to context initialization on server vs client (client-sided theme implementations, I'm looking at you), you shouldn't have negative performance impacts.
- [RootLayout](https://github.com/payloadcms/payload/blob/main/packages/next/src/layouts/Root/index.tsx) is rendered on the server and is the root-level layout for the admin app. It is a server component, and wraps the entire app in:
- [RootProvider](https://github.com/payloadcms/payload/blob/main/packages/ui/src/providers/Root/index.tsx) which is a client component, having 16 context providers by my count.
I think there's confusion/fear of using client components in general, that they somehow poison the speed and savings you get from nextjs. There is no intrinsic harm in using them as long as you are separating the provider into a client component and not unnecessarily marking something with "use client" that could otherwise be a server component (i.e, your context providers should live in client components, and should be imported into server components).
When you do this appropriately, and don't have mismatches/hydration errors due to context initialization on server vs client (client-sided theme implementations, I'm looking at you), you shouldn't have negative performance impacts.
Brown bear
Basically, context should be used for things that need to be handled on the client (and, of course, where context would be more useful than stuff like
For everything else, it should be kept on the server to prevent unnecessary client sided JS execution. How you will do so will vary based on what exactly your application is doing.
useState
, useReducer
, or other hooks). Examples would include: client-sided form validation, scroll-effects, audio/video playback, mouse movement/gestures, UI components with client-sided functionality (dropdowns, popovers, combo-boxes).For everything else, it should be kept on the server to prevent unnecessary client sided JS execution. How you will do so will vary based on what exactly your application is doing.
Cape lion
The fact that now you get server components that doesn’t mean it is bad practice to have client conponents. You still need interactivity in the majority of web apps. A lot of people just try to force everything server side. Well just use server components for what they are meant. If you need to share state between client components use context. If you need to share form data in nested components using a library like react-hook-form with the FormProvider is what you are after or why not if you want to get fancy use tanstack query wich is actually an async state management solution actually not a data fetching library like everyone thinks
@Cape lion The fact that now you get server components that doesn’t mean it is bad practice to have client conponents. You still need interactivity in the majority of web apps. A lot of people just try to force everything server side. Well just use server components for what they are meant. If you need to share state between client components use context. If you need to share form data in nested components using a library like react-hook-form with the FormProvider is what you are after or why not if you want to get fancy use tanstack query wich is actually an async state management solution actually not a data fetching library like everyone thinks
Flemish Giant
i think u r right. i also think server components are excellent for their intended use, but client components remain essential for interactivity in dynamic web apps.
@Cape lion The fact that now you get server components that doesn’t mean it is bad practice to have client conponents. You still need interactivity in the majority of web apps. A lot of people just try to force everything server side. Well just use server components for what they are meant. If you need to share state between client components use context. If you need to share form data in nested components using a library like react-hook-form with the FormProvider is what you are after or why not if you want to get fancy use tanstack query wich is actually an async state management solution actually not a data fetching library like everyone thinks
Flemish Giant
And what do u think about George Hulpoi's answer - "scalability relies on Software Design pattern and instead of looking to Reactish way of solving this problem, we should also look to Software Design Patterns and try to keep with Next.js way-of-doing-things." do u also agree with it?
Cape lion
Well, he has a point. For example, I like NextJS, and every time I have to build something I try to do it using Next. The thing is it depends on the usecase, for some tasks there are probably other tools more suitable. Like me, people who use React whithout a franework like Next, just got used to the patterns in React like context, and other stuff and they tend to use them even if they don’t need to. It’s like implementing state management for incrementing a counter.
@Brown bear <@1276154564982210683> I think server sided prop-drilling and client sided context both have their use cases, and should be used where appropriate. For example, PayloadCMS uses tons of global/root level context providers for their admin:
- [RootLayout](https://github.com/payloadcms/payload/blob/main/packages/next/src/layouts/Root/index.tsx) is rendered on the server and is the root-level layout for the admin app. It is a server component, and wraps the entire app in:
- [RootProvider](https://github.com/payloadcms/payload/blob/main/packages/ui/src/providers/Root/index.tsx) which is a client component, having 16 context providers by my count.
I think there's confusion/fear of using client components in general, that they somehow poison the speed and savings you get from nextjs. There is no *intrinsic* harm in using them as long as you are separating the provider into a client component and not unnecessarily marking something with "use client" that could otherwise be a server component (i.e, your context providers should live in client components, and should be imported into server components).
When you do this appropriately, and don't have mismatches/hydration errors due to context initialization on server vs client (client-sided theme implementations, I'm looking at you), you shouldn't have negative performance impacts.
Sloth bear
They are also using a lot of things on client-side. But usually, they stick on server-side and prop drills a lot informations (i18n, payload utils, collections, globals, database, etc).
Next.js and many frameworks came with the right question. If I want to render
If you're rendering static things, without using some React hooks or Browser API, what is the point of increasing static files size / initial page load time?
Next.js and many frameworks came with the right question. If I want to render
<h1>test</h1>
, why I should extra javascript code if is a static HTML element? That's the whole point of my arguments to stick to Next way-of-doing-things. If you're rendering static things, without using some React hooks or Browser API, what is the point of increasing static files size / initial page load time?
Sloth bear
For context, I am working in Angular since 2017. Angular lacks this server-side rendering (I mean, it can render the HTML on server-side, but it will hydrate everything with Javascript later).
Basically, if you want to have 100 components rendering an image and a text, you will have a Javascript code for that component. Therefore, you increase the memory size of webpage (100 * component mem size), static files size, initial loading time. And for what? You don't use Javascript at all, the solution is don't use a component (having a lot of static HTML code).
React is similar with Angular, therefore you will have a Javascript for that component and the same down-sides.
Next.js solves this issue, if can be rendered on server-side, keep it on server.
Basically, if you want to have 100 components rendering an image and a text, you will have a Javascript code for that component. Therefore, you increase the memory size of webpage (100 * component mem size), static files size, initial loading time. And for what? You don't use Javascript at all, the solution is don't use a component (having a lot of static HTML code).
React is similar with Angular, therefore you will have a Javascript for that component and the same down-sides.
Next.js solves this issue, if can be rendered on server-side, keep it on server.
I can understand that for some, it's harder to keep with this paradigm, and the easiest solution is to use
If you don't care so much about optimization or that you will send extra things on client, go ahead.
If you care about optimization and want to be lighting-fast, keep with Next.js way-of-doing-things.
useContext
to keep everything more organized.If you don't care so much about optimization or that you will send extra things on client, go ahead.
If you care about optimization and want to be lighting-fast, keep with Next.js way-of-doing-things.
Sloth bear
As I said, it's a complex problem that depends on many variables... time, deadline, your experience, etc.
If you are a new developer, trying to implement a Software Design Pattern may be a nightmare.
If you have a close deadline, you may not have enough time to analyze the problem and implement a Design Pattern.
Everyone will choose based on their knowledge and time.
If you are a new developer, trying to implement a Software Design Pattern may be a nightmare.
If you have a close deadline, you may not have enough time to analyze the problem and implement a Design Pattern.
Everyone will choose based on their knowledge and time.
managing react context for top level layout and needing to update it for every page.js access is a nightmare for me.
@Sloth bear They are also using a lot of things on client-side. But usually, they stick on server-side and prop drills a lot informations (i18n, payload utils, collections, globals, database, etc).
Next.js and many frameworks came with the right question. If I want to render `<h1>test</h1>`, why I should extra javascript code if is a static HTML element? That's the whole point of my arguments to stick to Next way-of-doing-things.
If you're rendering static things, without using some React hooks or Browser API, what is the point of increasing static files size / initial page load time?
Brown bear
Of course! I 100% agree. If it can be kept on the server, it should be. That doesn't mean that context and other client sided hooks are dead and gone/should be avoided at all costs. They (client hooks) should be used where necessary, i.e. when client sided reactivity is needed.
I'm not pointing to payload to say "they use it, so all use cases are fine!" I'm just trying to point out that client components and client sided reactivity still have their place. You should of course keep things on the server whenever possible so-as to minimize JavaScript delivered to the client and minimize execution time on the client. Of course, context should not be used simply to eliminate prop drilling on the server. Memoization and caching can help achieve the same effect without the negative performance impacts.
I'm not pointing to payload to say "they use it, so all use cases are fine!" I'm just trying to point out that client components and client sided reactivity still have their place. You should of course keep things on the server whenever possible so-as to minimize JavaScript delivered to the client and minimize execution time on the client. Of course, context should not be used simply to eliminate prop drilling on the server. Memoization and caching can help achieve the same effect without the negative performance impacts.
And I don't want to imply that you are arguing that client hooks are "evil" or anything. I just want to be clear on my stance.
tl;dr Do as much on the server as you can and don't reach for client sided hooks unless you want/need the client sided reactivity. I.e. don't use context for prop drilling of server data that will never change on the client
tl;dr Do as much on the server as you can and don't reach for client sided hooks unless you want/need the client sided reactivity. I.e. don't use context for prop drilling of server data that will never change on the client