Detecting Server vs Client Runtime and useEffect

Pro Members Only

This lesson is available if you have an active subscription.

Alternatively, some member might be able to gift it to you.

If you already have a subscription, you can sign in.

Professional NextJS Lessons

1.Course Intro
free
⏱️ 2:05
2.Get Setup
free
⏱️ 2:05
3.Project Template
free
⏱️ 5:45
4.Introducing FullStack React
free
⏱️ 4:57
5.App Router Reference
free
⏱️ 7:08
6.NextJS Server vs. "use client" Rendering
⏱️ 5:01
7.Nesting Server and Client Components
⏱️ 8:51
8.Client Only Components
⏱️ 3:48
9.Global CSS in NextJS
⏱️ 6:30
10.CSS Modules and SASS
⏱️ 4:15
11.Tailwind CSS
⏱️ 5:17
12.NextJS Custom Fonts
⏱️ 4:08
13.Static vs Dynamic Rendering
⏱️ 4:55
14.NextJS Link Component
⏱️ 3:20
15.NextJS Link Prefetching
⏱️ 5:49
16.Navigation Scroll with Link
⏱️ 2:02
17.Replace Navigation History
⏱️ 1:35
18.NextJS Image Component
⏱️ 7:01
19.Dynamic Image URLs
⏱️ 5:34
20.Safe Colocation with Private Folders
⏱️ 2:12
21.NextJS Route Groups
⏱️ 3:07
22.Dynamic Routes
⏱️ 5:37
23.NextJS API Routes
⏱️ 6:03
24.NextRequest and NextResponse
⏱️ 2:41
25.Cookies in API Handlers
⏱️ 4:25
26.React Suspense Simplified
⏱️ 2:23
27.Power of Suspense Boundaries
⏱️ 3:52
28.use Promises
⏱️ 3:24
29.Stream Promise Results from Server to Client
⏱️ 3:03
30.use Requires a Cached Promise
free
⏱️ 2:30
31.Suspense Error Boundaries
⏱️ 4:42
32.React Server Functions
⏱️ 4:50
33.Server Actions for Powerful Forms
⏱️ 5:35
34.useActionState to Simplify Form Actions
⏱️ 6:38
35.React Serializable Types
⏱️ 2:42
36.Create Dynamic Images with NextJS ImageResponse
⏱️ 5:54
37.Deploy NextJS Application to Production
⏱️ 3:51
38.NextJS Environment Variables Masterclass
⏱️ 3:50
39.Deploying and Managing Environment Variables
⏱️ 4:38
40.Using Databases for Dynamic Server Side State
free
⏱️ 7:34
41.Mastering NextJS Layout Files
⏱️ 4:54
42.Client State Management with NextJS
⏱️ 3:48
43.Client State Management In Action
⏱️ 8:04
44.Using Client State Management Libraries
⏱️ 5:25
45.Detecting Server vs Client Runtime and useEffect
⏱️ 4:33
46.Demystifying ISR vs SSR vs SSG
⏱️ 3:07
47.Static Site Generation or SSG with NextJS
⏱️ 3:16
48.Incremental Static Regeneration (ISR) Simplified
⏱️ 2:51
49.API Routes Caching with NextJS
⏱️ 3:05
50.Reference Guide to Caching for Modern NextJS
⏱️ 2:47
🚨 Work In Progress 🚧
Subscribe for Launch

Detecting Server vs Client Runtime and useEffect

Subscription Required

You must have an active subscription to access this content.
If you already have a subscription, you can sign in.

Core Concept

A common request for advanced uses cases is the ability to detect if your NexJS application code is executing on a server or a client environment.

We know that once deployed our nextjs application first executes on the server and then after it sends the initial response to the client, React hydrates our user interface and starts executing it on the browser.

While its executing on the server, you might access some data using a database driver, but when you are executing on the client you would need to access that information using an http call to an api.

So essentially you can abstract this behind a utility (e.g. loadData()) that might choose to do different things based on the environment it is currently executing in.

Using Environment Specific Globals

Fortunately its not that hard to detect the runtime environment. A simple way to achieve this is by checking the presence some global feature that is only present on the server or only present on the client.

A common pattern is:

const isClient = typeof window !== 'undefined';

This is demonstrated below with a component that renders different messages on Server vs. Client.

lib/DetectEnvironment.tsx
app/server/page.tsx
app/client/page.tsx
const isClient = typeof window !== "undefined";

export default function DetectEnvironment() {
return <div>{isClient ? "Client-side" : "Server-side"}</div>;
}

Beware of Hydration Errors

However the approach of using global variable detection is not ideal as it can result in hydration errors. What this means is that the content we render on the server might not match what is rendered on the client.

This is demonstrated below.

app/hydrate/page.tsx
lib/DetectEnvironment.tsx
"use client";

import DetectEnvironment from "@/lib/DetectEnvironment";

export default function Page() {
/**
* This will result in a runtime hydration error
* Reason:
* - client components render on server and hydrate on client
* - the output of both should match
* - this is not the case for <DetectEnvironment/>
*/
return <DetectEnvironment />;
}

Note that hydration errors will only happen if the rendered content on the server doesn’t match what we render on the client. If we take different execution paths based on the environment BUT return the same content, then it will not be an issue.

Safely Executing Client Specific Code

But what if we want to render something different, once our code has been successfully bootstrapped on the client. For that you can execute your logic on the component mounted event. We know from our React course that the built in hook for this purpose is called useEffect.

useEffect(() => {
// Runs only on the client
setIsClient(true);
}, []);

This is demonstrated below, the key thing to focus over here is that you can utilize the useEffect component did mount pattern to contain code that will only execute on the client.

lib/UpliftOnClient.tsx
app/page.tsx
"use client";

import { useEffect, useState } from "react";

export default function UpliftOnClient() {
const [isClient, setIsClient] = useState(false);

useEffect(() => {
// Runs only on the client
setIsClient(true);
}, []);

return <div>{isClient ? "Client-side" : "Server-side"}</div>;
}
javascript
typescript
react
playwright

Enjoy free content straight from your inbox 💌

No spam, unsubscribe at any time.

Transcript

00:00

A common request for advanced use cases is the ability to detect if your next JS application code is executing on a server or a client environment. We know that once deployed our next JS application first executes on the server and then after it sends the initial response to the client, react hydrates a user interface and starts executing it on the browser while it's executing on the server. You might access some data using a database driver, but when you are executing the same code on the client, you would need to access that information using an HTP call to an API. So essentially you can abstract this behind a utility

00:33

that might choose to do different things based on the environment it is currently executing in. Fortunately, it's not that hard to detect the runtime environment. A simple way to achieve this is by checking the presence of some global feature that is only present on the server or only present on the client. A common one that people use is the global window variable, which is something that is only present on the browser. So if window is not undefined, then we are guaranteed to be on the client. Let's build a simple component that uses this variable to render a different text message on the client and a different one on the server.

01:04

To demonstrate that this functions correctly, we will render it in a server environment and then in a client only environment to demonstrate it in a server environment, we import it into a server page and within our page function, we simply render out this component as we've demonstrated in our server versus client component lessons. This code will actually only ever execute on the server. Now let's create another page and render this component in a client only fashion. And as we've demonstrated in our lesson on client only components, we need to do two things. We need to be within the context of the use client directive and we need to import the component using Next Genna

01:38

and ensure that we turn server side rendering or SSR to false with our component successfully imported in a client only fashion, we simply render it out within the page with our server and our client pages created. Let's play around with this application within the browser and first step we visit our server page and you can see that our component has successfully detected the server side environment and rendered the text server side. Similarly, if you visit our client page, the same component renders the text client side. This proves that we can use global variables to detect if we are running our code on the server or on the client. However, this approach is not ideal

02:11

as it can result in hydration errors. What this means is that the content we render on the server might not match what is rendered on the client. To demonstrate this, instead of rendering our component in client only mode, we render it in a standard client component. We know from our previous lessons that client components actually run twice. They are initially rendered on the server and then they are hydrated on the client. So if you visit this particular page on the browser, you'll initially see the text server side and then once it is hydrated on the client, it swaps to the text client side. And this is something that will make React life difficult because it won't be able to reconcile which element rendered

02:46

on the server corresponds to which element rendered on the dorm, and therefore it would struggle to attach things like event handlers to the correct elements. And this issue is being highlighted by the next GS developer tools. You can see the message that hydration failed because the Server rendered HTML didn't match the client. Note that this will only happen if the final rendered result doesn't match. If we take different execution parts based on the environment but return the same content, then that would not be an issue. But what if you want to render something different once a code has been successfully bootstrapped on the client? For that, you can execute your logic on the component mounted event.

03:18

We know from our reactors that reacts built-in hook for this purpose is called use effect. To demonstrate this, we will build a new component that will uplift itself once it has successfully rendered on the client and decide to render something different to detect on Component mount. We bring in use effect and to modify what we are rendering after that event. We bring in use state within our component. We start off by assuming that we are initially running on the server, which is why we set this is client state variable to false, then we wait for a use effect to get called. And within that we know

03:49

that we will only execute on the client. So we modify that is client bullion to True? And finally, depending upon that is client bullion. We render different text messages. The key thing to focus over here is that you can utilize the use effect component did mount pattern to place code that will only execute on the client. Let's demonstrate this by rendering this component within a simple page. The component that we've created will render the same content on the server and during hydration, but once it is mounted, it swaps to a different message and if you just blink your eyes, you might have missed it. So I'll refresh this page a few times

04:22

so you can see the swap. This pattern of utilizing use effect prevents hydration errors because React is okay for you to make modifications to the dorm after the component is mounted.

Professional NextJS

Professional NextJS

1.Course Intro
free
⏱️ 2:05
2.Get Setup
free
⏱️ 2:05
3.Project Template
free
⏱️ 5:45
4.Introducing FullStack React
free
⏱️ 4:57
5.App Router Reference
free
⏱️ 7:08
6.NextJS Server vs. "use client" Rendering
⏱️ 5:01
7.Nesting Server and Client Components
⏱️ 8:51
8.Client Only Components
⏱️ 3:48
9.Global CSS in NextJS
⏱️ 6:30
10.CSS Modules and SASS
⏱️ 4:15
11.Tailwind CSS
⏱️ 5:17
12.NextJS Custom Fonts
⏱️ 4:08
13.Static vs Dynamic Rendering
⏱️ 4:55
14.NextJS Link Component
⏱️ 3:20
15.NextJS Link Prefetching
⏱️ 5:49
16.Navigation Scroll with Link
⏱️ 2:02
17.Replace Navigation History
⏱️ 1:35
18.NextJS Image Component
⏱️ 7:01
19.Dynamic Image URLs
⏱️ 5:34
20.Safe Colocation with Private Folders
⏱️ 2:12
21.NextJS Route Groups
⏱️ 3:07
22.Dynamic Routes
⏱️ 5:37
23.NextJS API Routes
⏱️ 6:03
24.NextRequest and NextResponse
⏱️ 2:41
25.Cookies in API Handlers
⏱️ 4:25
26.React Suspense Simplified
⏱️ 2:23
27.Power of Suspense Boundaries
⏱️ 3:52
28.use Promises
⏱️ 3:24
29.Stream Promise Results from Server to Client
⏱️ 3:03
30.use Requires a Cached Promise
free
⏱️ 2:30
31.Suspense Error Boundaries
⏱️ 4:42
32.React Server Functions
⏱️ 4:50
33.Server Actions for Powerful Forms
⏱️ 5:35
34.useActionState to Simplify Form Actions
⏱️ 6:38
35.React Serializable Types
⏱️ 2:42
36.Create Dynamic Images with NextJS ImageResponse
⏱️ 5:54
37.Deploy NextJS Application to Production
⏱️ 3:51
38.NextJS Environment Variables Masterclass
⏱️ 3:50
39.Deploying and Managing Environment Variables
⏱️ 4:38
40.Using Databases for Dynamic Server Side State
free
⏱️ 7:34
41.Mastering NextJS Layout Files
⏱️ 4:54
42.Client State Management with NextJS
⏱️ 3:48
43.Client State Management In Action
⏱️ 8:04
44.Using Client State Management Libraries
⏱️ 5:25
45.Detecting Server vs Client Runtime and useEffect
⏱️ 4:33
46.Demystifying ISR vs SSR vs SSG
⏱️ 3:07
47.Static Site Generation or SSG with NextJS
⏱️ 3:16
48.Incremental Static Regeneration (ISR) Simplified
⏱️ 2:51
49.API Routes Caching with NextJS
⏱️ 3:05
50.Reference Guide to Caching for Modern NextJS
⏱️ 2:47
🚨 Work In Progress 🚧
Subscribe for Launch