useEffect और Side Effects
Side effect क्या है?
Component का मुख्य काम JSX return करना है। इसके अलावा जो भी बाहर की दुनिया को छूता है — timer शुरू करना, localStorage पढ़ना, API call करना, document.title बदलना — वह side effect है। useEffect ऐसा code React के screen update करने के बाद चलाता है।
useEffect syntax
'use client'
import { useEffect, useState } from 'react'
useEffect(() => {
// 1. code that touches the outside world
return () => {
// 2. optional cleanup
}
}, [/* 3. dependencies */])Dependency array तय करता है कब चले
| आप लिखते हैं | Effect चलता है | किसके लिए |
|---|---|---|
useEffect(fn, []) | एक बार, पहले render के बाद | Timer शुरू, storage से load |
useEffect(fn, [q]) | पहले render + जब भी q बदले | Text बदलने पर search |
useEffect(fn) | हर render के बाद | कम ज़रूरत — सावधानी से |
Example: cleanup वाली live घड़ी
'use client'
import { useEffect, useState } from 'react'
export default function Clock() {
const [time, setTime] = useState(null) // null on the server, real time in the browser
useEffect(() => {
setTime(new Date())
const id = setInterval(() => setTime(new Date()), 1000) // start
return () => clearInterval(id) // cleanup: stop
}, []) // [] = run once after the first render
return <p>⏰ {time ? time.toLocaleTimeString('en-IN') : '--:--:--'}</p>
}clearInterval के बिना page छोड़ने पर भी timer background में चलता रहेगा — यह memory leak है। Cleanup function इसे रोकता है।
null से शुरू करके time effect के अंदर set करते हैं। Server और browser की घड़ी अलग होती है, और render में सीधे time दिखाने से hydration mismatch warning आती है।Example: localStorage में note save करना
'use client'
import { useEffect, useState } from 'react'
export default function Notes() {
const [text, setText] = useState('')
// Load once from the browser's storage
useEffect(() => {
setText(localStorage.getItem('note') || '')
}, [])
// Save every time `text` changes
useEffect(() => {
localStorage.setItem('note', text)
}, [text])
return <textarea value={text} onChange={(e) => setText(e.target.value)} rows={4} />
}localStorage सिर्फ़ browser में होता है, इसलिए इसे useEffect के अंदर ही use करें (component के top पर नहीं, क्योंकि वह server पर भी चलता है)।
Example: fetch से live search
'use client'
import { useEffect, useState } from 'react'
export default function LiveSearch() {
const [q, setQ] = useState('')
const [results, setResults] = useState([])
useEffect(() => {
if (!q) return setResults([])
const controller = new AbortController()
const timer = setTimeout(async () => { // wait 300 ms after typing stops
const res = await fetch(`/api/courses?q=${encodeURIComponent(q)}`, { signal: controller.signal })
const data = await res.json()
setResults(data.courses)
}, 300)
return () => { clearTimeout(timer); controller.abort() } // cancel old request
}, [q])
return (
<div>
<input value={q} onChange={(e) => setQ(e.target.value)} placeholder="Search courses" />
<ul>{results.map((c) => <li key={c.slug}>{c.title} – ₹{c.fee}</li>)}</ul>
</div>
)
}Next.js में data के लिए server बेहतर
जो data page का हिस्सा है (course list, blog posts), उसके लिए Server Component आसान और SEO के लिए बेहतर है — HTML में data पहले से होता है और Google पढ़ लेता है:
// app/courses/page.jsx — Server Component: no useEffect, no loading spinner needed
import { searchCourses } from '@/lib/courses'
export default async function CoursesPage({ searchParams }) {
const { q = '' } = await searchParams
const list = searchCourses(q) // runs on the server
return <ul>{list.map((c) => <li key={c.slug}>{c.title}</li>)}</ul>
}useEffect + fetch (client)
- Page पहले खाली / spinner दिखाता है
- Browser से extra request
- Search engine content miss कर सकते हैं
- Live, user वाले updates के लिए अच्छा
Server Component (await)
- HTML data के साथ आता है
- Loading flicker नहीं
- SEO के लिए सबसे अच्छा
- Page content के लिए अच्छा
आम गलतियाँ
- बिना dependency array के effect में state set करना → infinite render loop।
- Dependencies छूट जाना → effect पुरानी value use करता है। Effect में use होने वाले component के हर variable को डालें।
- Effect function को ही
asyncबनाना → allowed नहीं। अंदर async function बनाकर call करें। useEffectके बाहरwindowयाlocalStorageuse करना → server पर "window is not defined"।
सारांश
useEffectrender के बाद side effects चलाता है।- Dependency array तय करता है कब चले; काम undo करने के लिए cleanup function return करें।
- Timers, storage, subscriptions और live search के लिए use करें।
- Next.js में page data Server Components में fetch करें।
एक component बनाइए जो state के count के हिसाब से document.title को "(3) New messages" कर दे, और component हटने पर title वापस कर दे।
