Using Browser APIs
| Topic | Source |
|---|---|
| React | All 29 Next.js Mistakes Beginners Make - YouTube |
In Next.js, if you are using browser APIs in client components, you need to ensure that the code runs only on the client side. This is important because browser APIs like window, document, or localStorage are not available during server-side rendering (SSR). Here's how you can safely use browser APIs in client components:
1. Check if the Code is Running on the Client Side
You can use the typeof window !== 'undefined' check to ensure the code runs only in the browser.
import { useEffect, useState } from 'react';
export default function ClientComponent() {
const [windowWidth, setWindowWidth] = useState(0);
useEffect(() => {
// Ensure this runs only on the client side
if (typeof window !== 'undefined') {
setWindowWidth(window.innerWidth);
const handleResize = () => {
setWindowWidth(window.innerWidth);
};
window.addEventListener('resize', handleResize);
// Cleanup the event listener
return () => {
window.removeEventListener('resize', handleResize);
};
}
}, []);
return <div>Window Width: {windowWidth}px</div>;
}
2. Use Dynamic Imports for Client-Side Only Code
If you need to import a library or component that relies on browser APIs, you can use Next.js's dynamic import with the ssr: false option to ensure it only loads on the client side.
import dynamic from 'next/dynamic';
// Load this component only on the client side
const ClientOnlyComponent = dynamic(() => import('../components/ClientOnlyComponent'), {
ssr: false,
});
export default function Home() {
return (
<div>
<h1>Home Page</h1>
<ClientOnlyComponent />
</div>
);
}
3. Access Browser APIs in useEffect
Since useEffect runs only on the client side after the component mounts, it's a safe place to use browser APIs.
import { useEffect, useState } from 'react';
export default function LocalStorageExample() {
const [value, setValue] = useState('');
useEffect(() => {
// Access localStorage only on the client side
if (typeof window !== 'undefined') {
const storedValue = localStorage.getItem('myKey');
if (storedValue) {
setValue(storedValue);
}
}
}, []);
const saveToLocalStorage = () => {
if (typeof window !== 'undefined') {
localStorage.setItem('myKey', 'Hello, LocalStorage!');
setValue('Hello, LocalStorage!');
}
};
return (
<div>
<p>Stored Value: {value}</p>
<button onClick={saveToLocalStorage}>Save to LocalStorage</button>
</div>
);
}
4. Use the useClient Hook (Optional)
If you're using React Server Components (RSC) in Next.js 13+, you can mark a component as client-side only by adding the 'use client' directive at the top of the file.
'use client'; // Mark this component as client-side only
import { useEffect, useState } from 'react';
export default function ClientComponent() {
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
}, []);
if (!mounted) {
return <div>Loading...</div>;
}
return <div>Browser API is available!</div>;
}
5. Avoid Direct Usage in Render
Never directly use browser APIs in the render phase of a component, as this will cause errors during SSR.
// โ Avoid this
export default function BadExample() {
const width = window.innerWidth; // This will break during SSR
return <div>Window Width: {width}px</div>;
}