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>;
}