🧠 Introduction to useEffect and Next.js
If you're learning React and jump into Next.js, you might quickly notice something frustrating: useEffect doesn’t behave the way you expect.
Understanding why useEffect breaks in Next.js — and how to fix it is super important if you want to build modern apps without bugs.
Let’s break it down in the simplest way possible 👇
🔍 What is useEffect in React
useEffect is a React Hook that runs code after the component renders.
👉 Common uses:
Fetching data
Accessing browser APIs (like
window)Setting timers
Example:
useEffect(() => {
console.log("Component mounted");
}, []);⚡ What makes Next.js different from React
Here’s the key difference:
React | Next.js |
|---|---|
Runs in browser | Runs on server + browser |
Client-side rendering | Server-side rendering (SSR) |
👉 This is where problems start!
🚨 Why useEffect breaks in Next.js
🖥️ Server-Side Rendering (SSR) vs Client-Side Rendering
Next.js first renders your page on the server, then sends it to the browser.
But...
👉 useEffect ONLY runs in the browser (client-side).
❗ useEffect runs only on the client
That means:
It does NOT run during server rendering
It runs AFTER hydration (when React takes over)
⚠️ Hydration mismatch issues
Sometimes:
Server output ≠ Client output
This causes errors like:
Hydration failed because the initial UI does not match😵 Common Problems Developers Face
1. useEffect not running
Because you're expecting it to run on the server — but it doesn't.
2. "window is not defined" error
This is the MOST common error.
Why?
👉 Because window exists only in the browser, not on the server.
3. Infinite loops in useEffect
Bad dependency arrays can cause:
useEffect(() => {
setState(value);
});👉 This runs forever 😬
💡 Real Example: useEffect Breaking in Next.js
❌ Problem Code
import { useEffect } from "react";
export default function Page() {
useEffect(() => {
console.log(window.innerWidth);
}, []);
return <div>Hello</div>;
}💥 Why it fails
Next.js tries to render this on the server
windowdoes NOT exist thereResult: crash or error
🛠️ Step-by-Step Fixes
✅ Fix 1: Use "use client" directive
In Next.js (App Router):
"use client";
import { useEffect } from "react";
export default function Page() {
useEffect(() => {
console.log("Runs only on client");
}, []);
return <div>Hello</div>;
}👉 This ensures the component runs only in the browser.
✅ Fix 2: Check for window safely
useEffect(() => {
if (typeof window !== "undefined") {
console.log(window.innerWidth);
}
}, []);👉 Prevents server crash.
✅ Fix 3: Use dynamic import with SSR disabled
import dynamic from "next/dynamic";
const NoSSRComponent = dynamic(() => import("./MyComponent"), {
ssr: false,
});👉 This completely skips server rendering.
✅ Fix 4: Fix dependency array issues
Bad:
useEffect(() => {
setCount(count + 1);
});Good:
useEffect(() => {
setCount(count + 1);
}, []);👉 Always define dependencies properly.
📌 Best Practices for useEffect in Next.js
✔️ Keep logic client-side only
Only use useEffect for:
Browser APIs
DOM updates
✔️ Avoid heavy logic in useEffect
Don’t:
Fetch large data unnecessarily
Run expensive calculations
✔️ Use proper dependency arrays
Always ask:
👉 "When should this run?"
🚀 Advanced Tips
useLayoutEffect vs useEffect
useEffect→ runs after paintuseLayoutEffect→ runs before paint
⚠️ In Next.js:
Avoid
useLayoutEffecton server
Handling API calls properly
Better approach in Next.js:
👉 Use server-side data fetching:
fetch()in Server ComponentsgetServerSideProps(older)
❓ FAQs
1. Why does useEffect not run on server?
Because it is designed to run only in the browser after rendering.
2. What causes "window is not defined"?
Using browser APIs during server rendering.
3. How to fix hydration errors?
Ensure server and client output match, or use client-only components.
4. Should I always use "use client"?
No. Only when you need client-side features like hooks.
5. Is useEffect bad in Next.js?
Not at all — just use it correctly.
6. What is the safest way to use useEffect?
Use it only for browser-related logic and guard with checks.
🏁 Conclusion
Now you clearly understand why useEffect breaks in Next.js — and how to fix it.
👉 The main issue is simple:
Next.js runs on the server
useEffect runs on the client
Once you understand this difference, everything becomes much easier.
💡 Just remember:
Use
"use client"when neededAvoid server-only errors
Write clean and safe useEffect logic