Client-only modules let you run code only in the browser, not on the server. This helps when you use features that need the browser, like window or document.
Client-only modules in NextJS
import dynamic from 'next/dynamic'; const ClientComponent = dynamic(() => import('./ClientComponent'), { ssr: false });
Use dynamic from Next.js to load modules only on the client.
Setting ssr: false disables server-side rendering for that module.
Map component only in the browser because it uses browser APIs.import dynamic from 'next/dynamic'; const Map = dynamic(() => import('./Map'), { ssr: false });
import dynamic from 'next/dynamic'; const ClientOnlyComponent = dynamic(() => import('./ClientOnlyComponent'), { ssr: false });
This example shows a page that loads a ClientOnly component only in the browser. The component uses window.innerWidth, which is not available on the server. Using dynamic with ssr: false prevents errors and shows the width after loading.
import dynamic from 'next/dynamic'; import React from 'react'; const ClientOnly = dynamic(() => import('./ClientOnly'), { ssr: false }); export default function Home() { return ( <main> <h1>Welcome to Client-only Modules Demo</h1> <ClientOnly /> </main> ); } // ClientOnly.js import React, { useEffect, useState } from 'react'; export default function ClientOnly() { const [width, setWidth] = useState(0); useEffect(() => { setWidth(window.innerWidth); }, []); return <p>Window width is: {width}</p>; }
Client-only modules help avoid errors from using browser-only features on the server.
Remember to import dynamic from 'next/dynamic' to use this feature.
Use client-only modules to improve user experience by loading interactive parts only in the browser.
Client-only modules run only in the browser, not on the server.
Use dynamic with ssr: false to load these modules.
This helps when using browser APIs or improving performance.
Practice
Solution
Step 1: Understand client-only module purpose
Client-only modules run only in the browser to avoid errors from browser-specific APIs on the server.Step 2: Compare options
They run only in the browser, avoiding server errors with browser APIs. correctly states this purpose. Options B, C, and D describe unrelated or incorrect behaviors.Final Answer:
They run only in the browser, avoiding server errors with browser APIs. -> Option AQuick Check:
Client-only modules = browser-only code [OK]
- Thinking client-only modules run on the server
- Confusing client-only with static generation
- Assuming client-only modules improve server speed
MyComponent using Next.js dynamic import?Solution
Step 1: Recall dynamic import with ssr: false
To load client-only modules, Next.js requires dynamic import with { ssr: false } to disable server-side rendering.Step 2: Analyze options
import dynamic from 'next/dynamic'; const MyComponent = dynamic(() => import('./MyComponent'), { ssr: false }); uses dynamic import with ssr: false correctly. import MyComponent from './MyComponent'; is a normal import (runs on server too). const MyComponent = require('./MyComponent'); uses require, not recommended in Next.js. import dynamic from 'next/dynamic'; const MyComponent = dynamic(() => import('./MyComponent')); misses ssr: false, so it runs on server.Final Answer:
import dynamic from 'next/dynamic'; const MyComponent = dynamic(() => import('./MyComponent'), { ssr: false }); -> Option BQuick Check:
Use dynamic + ssr: false for client-only imports [OK]
- Forgetting { ssr: false } disables server rendering
- Using normal import for client-only modules
- Using require instead of import
import dynamic from 'next/dynamic';
const ClientOnly = dynamic(() => import('./ClientOnlyComponent'), { ssr: false });
export default function Page() {
return (
Welcome
);
}Assuming
ClientOnlyComponent renders <p>Loaded on client</p>.Solution
Step 1: Understand dynamic import with ssr: false
The componentClientOnlyloads only on the client, so server renders without it initially, showing a loading placeholder.Step 2: Predict final render output
Before hydration, the placeholderLoading...is shown. After hydration,ClientOnlyComponentrenders<p>Loaded on client</p>. The initial render output includes the heading and loading placeholder.Final Answer:
<div><h1>Welcome</h1><p>Loading...</p></div> -> Option CQuick Check:
Client-only modules show loading placeholder on server render [OK]
- Expecting client-only content on server render
- Assuming error occurs without server rendering
- Thinking loading placeholder always shows
import dynamic from 'next/dynamic';
const Widget = dynamic(() => import('./Widget'));
export default function Home() {
return ;
}What is the main problem here?
Solution
Step 1: Check dynamic import options
The code uses dynamic import but omits { ssr: false }, so Next.js tries to render Widget on the server.Step 2: Understand consequences
If Widget uses browser-only APIs, server rendering will fail or cause errors. Adding { ssr: false } prevents server rendering.Final Answer:
Missing { ssr: false } causes server to try rendering Widget, which may fail. -> Option AQuick Check:
Always add ssr: false for client-only modules [OK]
- Forgetting ssr: false option
- Thinking dynamic import syntax is wrong without require
- Assuming Suspense is mandatory for dynamic imports
import dynamic from 'next/dynamic';
const BrowserOnly = dynamic(() => import('./BrowserOnlyComponent'), { ssr: false });
export default function Page() {
return (
Client-only Example
);
}What else should you do inside
BrowserOnlyComponent to safely use browser APIs?Solution
Step 1: Understand client-only import
Dynamic import with { ssr: false } ensures the component loads only on the client, avoiding server errors.Step 2: Use useEffect for browser APIs
Inside the component, browser APIs should be called inside useEffect to run after mounting, ensuring the DOM and window objects exist.Final Answer:
Use React's useEffect hook to run browser API code after component mounts. -> Option DQuick Check:
Browser APIs inside useEffect = safe client use [OK]
- Calling browser APIs directly in render causing errors
- Trying to use browser APIs on server via getServerSideProps
- Relying on try-catch instead of proper lifecycle hooks
Ready to prove it?
Pass the test and this pattern moves unknown
