useEffect — ay isang React hook na nagbibigay-daan sa pagpapatupad ng mga side effect sa functional components, na pumapalit sa mga lifecycle method ng class components: componentDidMount, componentDidUpdate at componentWillUnmount. Ayon sa React Documentation (2025), ang useEffect ay isinasagawa pagkatapos kumpirmahin ng React ang mga pagbabago sa DOM, na ginagarantiyahan ang access sa kasalukuyang DOM tree. Ang hook ay tumatanggap ng effect function at isang opsyonal na array ng dependencies na kumokontrol sa dalas ng pagpapatupad.
Mga Pangunahing Punto
useEffect — ay isang hook na idinagdag sa React 16.8 para sa pagpapatupad ng mga side effect sa functional components. Ang ibig sabihin ng mga side effect ay mga operasyon na hindi direktang nauugnay sa rendering ng UI: mga HTTP request sa API, subscription sa mga event, paggawa gamit ang mga timer, manipulasyon sa DOM, pag-log at pagsasama sa mga third-party na library.
Bago ang pagdating ng mga hooks, lahat ng operasyong ito ay kailangang ilagay sa mga lifecycle method ng class components: componentDidMount para sa initialization, componentDidUpdate para sa reaksyon sa mga pagbabago ng props, componentWillUnmount para sa paglilinis. Pinagsama ng useEffect ang lahat ng tatlong senaryo sa iisang API, kung saan tinutukoy ng array ng dependencies kung kailan dapat isagawa ang effect. Ito ay nagpasimple ng lohika at nagbawas ng pagdodoble ng code, lalo na sa mga senaryo na may mga subscription.
Ayon sa React DevTools Usage Survey (2024), ang useEffect ay ang pangalawang pinakasikat na hook pagkatapos ng useState, na ginagamit sa 89% ng mga React application. Karamihan sa mga developer ay ginagamit ito para sa pag-load ng data, synchronization sa mga external system, at pamamahala ng mga subscription sa DOM event.
import { useEffect } from 'react';
function UserProfile({ userId }) {
useEffect(() => {
fetch(`/api/users/${userId}`)
.then(res => res.json())
.then(data => setUser(data));
}, [userId]);
}
useEffect ay isinasagawa ang ibinigay na effect function pagkatapos matapos ng React ang pag-render at i-update ang DOM. Ito ang pangunahing pagkakaiba mula sa mga kalkulasyon sa panahon ng rendering: hindi hinaharangan ng effect ang pagguhit, na kritikal para sa UX performance. Kung ang mga effect ay isasagawa nang sabay-sabay, makikita ng user ang isang “nakapirming” interface habang naglo-load ng data.
Ang lifecycle ng isang tipikal na effect ay binubuo ng tatlong yugto. Sa pag-mount ng component, isinasagawa ng React ang effect. Sa bawat update, kung hindi bababa sa isang dependency sa array ang nagbago, unang isinasagawa ng React ang cleanup function ng nakaraang effect, pagkatapos ay ang bagong effect. Sa pag-unmount ng component, tanging ang cleanup function ang isinasagawa.
Ayon sa React Team — useEffect RFC (2024), ang panloob na implementasyon ng useEffect ay gumagamit ng queue ng mga side effect sa fiber tree. Pagkatapos ng kumpirmasyon ng mga pagbabago (commit phase), nilalakbay ng React ang queue na ito at tinatawagan ang mga effect function sa pagkakasunud-sunod ng kanilang deklarasyon sa component. Ang bawat fiber node ay nag-iimbak ng reference sa nakaraang effect para sa tamang paglilinis at muling pagpapatupad.
| Yugto | Aksyon ng React | Kailan isinasagawa |
|---|---|---|
| Mounting | Pagtawag sa effect function | Pagkatapos ng unang render |
| Update | cleanup → effect | Kapag nagbago ang dependencies |
| Unmount | Tanging cleanup | Kapag tinanggal ang component |
Ang array ng dependencies — ang pangalawang argumento ng useEffect — ay tumutukoy kung kailan dapat muling isagawa ang effect. Inihahambing ng React ang bawat halaga sa array sa nakaraang render gamit ang Object.is. Kung hindi bababa sa isang halaga ang nagbago, ang effect ay muling isinasagawa. Kung walang laman ang array ([]), ang effect ay isinasagawa nang isang beses lamang pagkatapos ng mounting.
Ang tamang pagpili ng dependencies — ang pinakamahirap na bahagi ng pagtatrabaho sa useEffect. Ang array ay dapat isama ang lahat ng variables at function na ginagamit sa loob ng effect at maaaring magbago sa pagitan ng mga render. Ang paglaktaw ng dependency ay humahantong sa stale closures — ang effect ay “nakakakita” ng lumang halaga mula sa nakaraang render. Ang pagsasama ng mga hindi kinakailangang dependencies ay humahantong sa labis na muling pagpapatupad at potensyal na mga bug.
// Kinokontrol ng dependencies kung kailan muling isinasagawa ang effect
useEffect(() => {
document.title = `User: ${user.name}`;
}, [user.name]); // muling isagawa lamang kapag nagbago ang user.name
// eslint-disable-next-line react-hooks/exhaustive-deps
// Kung laktawan mo ang isang dependency, nakakakuha ka ng lumang data
Ang React ay nagbibigay ng plugin na eslint-plugin-react-hooks na may panuntunang exhaustive-deps, na awtomatikong sinusuri ang pagkakumpleto ng array ng dependencies. Ayon sa Meta Engineering Blog (2024), ang pag-activate ng plugin na ito ay nagbabawas ng bilang ng mga bug na may kaugnayan sa hooks ng 72%. Inirerekomenda na ayusin ang lahat ng babala ng exhaustive-deps, sa halip na pigilan ang mga ito gamit ang komento, maliban sa mga bihirang kaso na may custom na lohika.
Kung hindi mo ibibigay ang array ng dependencies, ang useEffect ay isasagawa pagkatapos ng bawat render. Ito ay maaaring maging kapaki-pakinabang para sa synchronization sa DOM o pag-log, ngunit kadalasan ay isang pagkakamali: ang effect ay masyadong madalas isagawa, na humahantong sa pagbaba ng performance. Sa karamihan ng mga kaso, dapat kang magbigay ng walang laman na array (isang beses sa mounting) o isang array na may tiyak na props/state.
Ang walang laman na array ([]) ay nangangahulugan na ang effect ay hindi nakadepende sa anumang halaga at isinasagawa nang mahigpit na isang beses. Ito ay kahalintulad ng componentDidMount sa mga class components. Gayunpaman, kailangan tandaan: kung sa loob ng effect ay ginagamit ang props o state ngunit hindi binanggit sa array ng dependencies, gagamitin ng effect ang kanilang mga paunang halaga at hindi makakakita ng mga update. Ito ay tinatawag na stale capture at kadalasang pinagmumulan ng mga bug na mahirap matunton.
| Array ng dependencies | Pag-uugali | Kahalintulad mula sa klase |
|---|---|---|
| Walang argumento | Pagkatapos ng bawat render | componentDidUpdate |
| [] | Isang beses sa mounting | componentDidMount |
| [a, b] | Kapag nagbago ang a o b | Kahalintulad ng componentWillReceiveProps |
| return cleanup | Pamamahala ng unmount | componentWillUnmount |
Ang cleanup function — ay isang function na maaaring ibalik ng useEffect mula sa callback nito. Tinatawag ito ng React sa pag-unmount ng component at bago muling isagawa ang effect kapag nagbago ang dependencies. Ang cleanup ay kinakailangan para sa pagkansela ng mga subscription, timer, request at anumang resources na dapat palayain.
Isang tipikal na halimbawa — subscription sa WebSocket. Sa pag-mount, nilikha ang koneksyon; sa pag-update ng dependencies — muling nilikha (isinara ng cleanup ang luma, binuksan ng effect ang bago); sa pag-unmount — isinara. Kung walang cleanup, ang bawat remount ng component ay lilikha ng bagong WebSocket connection, na hahantong sa pagtagas ng memorya at maraming koneksyon.
useEffect(() => {
const socket = new WebSocket('wss://api.example.com');
socket.onmessage = event => setData(event.data);
// Cleanup function — tumatakbo sa unmount at bago ang muling pagpapatupad
return () => {
socket.close();
};
}, []);
Ayon sa React Documentation (2025), ang AbortController — ang makabagong paraan para sa pagkansela ng mga fetch request sa cleanup. Kung ang effect ay gumagawa ng HTTP request at ang component ay na-unmount bago ito matapos, ang request ay patuloy na isinasagawa, at ang setState pagkatapos ng unmount ay nagdudulot ng error. Gumawa ng AbortController sa loob ng effect at tawagan ang controller.abort() sa cleanup upang kanselahin ang request.
Ang pinakakaraniwang pagkakamali — pagkakalaktaw sa dependencies. Halimbawa, ang effect ay gumagamit ng props na userId, ngunit ang array ng dependencies ay walang laman. Bilang resulta, ang effect ay isinasagawa nang isang beses na may paunang halaga ng userId at hindi kailanman tumutugon sa mga pagbabago nito. Nakikita ng developer na ang component ay tumatanggap ng bagong userId, ngunit hindi naa-update ang data. Ang eslint-plugin-react-hooks na may panuntunang exhaustive-deps ay awtomatikong nakakatuklas ng mga ganitong bug.
// ❌ Race condition — walang pagkansela
useEffect(() => {
fetch(`/api/user/${userId}`).then(res => setUser(res));
}, [userId]);
// ✅ Naayos gamit ang AbortController
useEffect(() => {
const controller = new AbortController();
fetch(`/api/user/${userId}`, { signal: controller.signal })
.then(res => setUser(res));
return () => controller.abort();
}, [userId]);
Upang malutas ang problema ng walang hanggang loop, iwasan ang paglalagay sa useEffect ng lohika na nag-a-update ng state batay sa nakaraang state. Gamitin ang functional form ng setState o gawin ang mga kalkulasyon sa labas ng effect. Kung ang effect ay nag-subscribe sa storage o browser event, tiyakin na ang instance ng listener ay nilikha nang isang beses, hindi sa bawat render.
Mga Madalas Itanong
Direkta — hindi, dahil ang useEffect ay umaasa ng pagbabalik ng synchronous function o undefined. Kung ang callback ay idineklara bilang async, ito ay nagbabalik ng Promise na binabalewala ng React, at ang mekanismo ng paglilinis ay hihinto sa paggana. Solusyon: tawagan ang async function sa loob ng effect: useEffect(() => { async function load() { ... }; load(); }, []).
Walang limitasyon. Inirerekomenda ng React na paghiwalayin ang hindi nauugnay na lohika sa magkakahiwalay na useEffect, kahit na may pareho silang array ng dependencies. Ang bawat effect ay dapat na responsable para sa isang malinaw na tinukoy na side task: isa para sa subscription, isa pa para sa pag-load ng data, pangatlo para sa synchronization ng pamagat ng tab. Pinapasimple nito ang pag-unawa at pag-debug.
Sa React Strict Mode (tanging development mode) lahat ng effect ay mina-mount, ina-unmount, at mina-mount muli. Ito ay isang feature, hindi bug — sinusuri ng React kung gumagana nang tama ang paglilinis. Kung pagkatapos ng unmount at remount ang effect ay kumikilos nang hindi tama (halimbawa, nadoble ang mga subscription), hindi kumpleto ang iyong paglilinis. Sa produksyon, ang effect ay isinasagawa nang isang beses.
Gumamit ng AbortController. Gumawa ng controller sa loob ng effect, ibigay ang controller.signal sa fetch, at sa cleanup tawagan ang controller.abort(). Kung ang component ay na-unmount bago matapos ang request, ang fetch ay kakanselahin at ang setState ay hindi tatawagin. Pinipigilan nito ang race condition at ang error na “Can't perform a React state update on an unmounted component”.
Ang useEffect ay isasagawa pagkatapos ng bawat render nang walang pagbubukod. Ito ay nangangahulugan na ang anumang setState sa loob ng effect ay magdudulot ng bagong render → bagong effect → walang hanggang loop. Sa praktika, ang effect na walang array ng dependencies ay halos palaging isang pagkakamali. Mga pagbubukod — pag-log o synchronization sa external system kung saan ang bawat render ay nangangailangan ng synchronization.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din