useState: ano ito, state hook at syntax sa React

May-akda: IT Sectr Nai-publish: 2026-07-04 Oras ng pagbabasa: 9 min

useState — ay isang built-in na React hook na nagpapahintulot sa mga functional component na pamahalaan ang lokal na state nang hindi ginagawang class component. Ipinakilala ng React 16.8 ang mga hooks, at ang useState ang naging pinaka-ginagamit sa kanila, na pumalit sa this.state at this.setState mula sa class approach. Ayon sa React Documentation (2025), mahigit 80% ng mga component sa modernong React application ay gumagamit ng useState para sa pamamahala ng data ng form, interface flags, at mga counter. Ang hook ay nagbabalik ng tuple na binubuo ng kasalukuyang halaga at setter function na nag-a-update ng state at nag-uumpisa ng re-render ng component.

Mga Pangunahing Punto

  • useState — hook para sa pamamahala ng lokal na state sa mga functional React component.
  • Tuple — nagbabalik ng pares [halaga, setter], kung saan ang setter ay function na nag-a-update ng state.
  • Re-render — ang pagtawag sa setter ay laging nag-uumpisa ng pag-redraw ng component na may bagong halaga.
  • Mga uri ng data — gumagana ang useState sa mga numero, string, array, object, at boolean na halaga.
  • Imutabilidad — ang state ay hindi direktang ma-mutate, sa pamamagitan lamang ng setter function.

Ano ang useState sa React

useState — ay ang pangunahing React hook, idinagdag sa bersyon 16.8, na nagbibigay sa mga functional component ng kakayahang mag-imbak at magbago ng lokal na state. Bago dumating ang mga hooks, ang state ay magagamit lamang sa mga class component sa pamamagitan ng this.state at this.setState, na ginagawang pampakita lamang ang mga functional component. Inalis ng useState ang limitasyong ito, na nagpapahintulot na isulat ang buong application sa mga functional component.

Ang hook ay tumatanggap ng isang argumento — ang paunang halaga ng state — at nagbabalik ng array ng dalawang elemento. Ang unang elemento ay ang kasalukuyang halaga ng state, ang pangalawa ay ang function para i-update ito. Ginagarantiya ng React na ang setter function ay stable at hindi nagbabago sa pagitan ng mga render, na nagpapahintulot ng ligtas na pagpasa nito sa mga child component at paggamit sa mga closure.

Ayon sa React DevTools Usage Survey (2024), ang useState ay ginagamit sa 96% ng mga React application, ginagawa itong pinakalaganap na hook sa ecosystem. Kahit sa mga application na gumagamit ng global state sa pamamagitan ng Redux o Zustand, ang lokal na state sa pamamagitan ng useState ay nananatiling pangunahing mekanismo ng pamamahala ng UI state — bukas na modals, halaga ng input field, aktibong tab.

jsx
import { useState } from 'react';

function Counter() {
    const [count, setCount] = useState(0);

    return (
        <div>
            <p>Count: {count}</p>
            <button onClick={() => setCount(count + 1)}>
                Increment
            </button>
        </div>
    );
}

Paano gumagana ang useState

Ang panloob na mekanismo ng useState ay nakabatay sa fiber node system ng React. Ang bawat component sa React ay kinakatawan ng fiber node na nag-iimbak ng nauugnay na listahan ng mga hooks sa anyo ng naka-link na listahan. Kapag ang component ay tumawag ng useState, ang React ay lumilikha ng bagong node sa listahang ito at nag-iimbak dito ng kasalukuyang halaga ng state at reference sa queue ng mga update.

Kapag tinawag ang setter function, hindi agad ina-update ng React ang state. Sa halip, inilalagay nito ang update sa queue (pending state queue), nag-iiskedyul ng re-render ng component, at sa susunod na render lamang kinakalkula ang bagong state batay sa luma at mga inilapat na update. Tinitiyak nito ang batching — kung sa isang event handler ay tinawag mo ang setter nang tatlong beses, igrupo ng React ang mga ito sa isang re-render.

Ayon sa React Team — React 18 Working Group (2024), ang automatic batching ay pinalawak sa React 18: ngayon ang mga state update ay naka-grupo hindi lamang sa mga event handler, kundi pati na rin sa setTimeout, Promise callbacks, at native handler. Nagbigay ito ng pagtaas ng performance hanggang 30% sa mga senaryo na may maraming state update.

Functional na pag-update ng state

Kapag ang bagong state ay nakadepende sa nauna, gamitin ang functional form ng setter: setCount(prev => prev + 1). Ipinapasa ng React sa function ang aktwal na halaga ng state sa oras ng paglalapat ng update, na ginagarantiya ang kawastuhan kahit sa naka-batch na mga update. Kung wala ang functional form, ang setCount(count + 1) ay maaaring gumamit ng lumang halaga kung ito ay tinawag nang ilang beses nang sunod-sunod.

jsx
// Lazy initialization — isang beses lang tumatakbo
setCount(prev => prev + 1);
setCount(prev => prev + 1);
setCount(prev => prev + 1);
// Result: count increased by 3

// NOT batch-safe: stale closure
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
// Result: count increased by 1 (stale closure)

Syntax ng useState: deklarasyon at pag-update

Ang pangunahing syntax ng useState ay napakaikli: const [state, setState] = useState(initialValue). Ang paunang halaga ay ginagamit lamang sa unang render; sa mga susunod na render ay binabalewala ito ng React at ibinabalik ang kasalukuyang naka-imbak na halaga. Kung ang paunang pagkalkula ay nangangailangan ng mamahaling operasyon, magpasa ng initializer function: useState(() => computeExpensiveInitial()).

Ang lazy initialization (lazy initial state) ay lalong mahalaga kapag ang paunang halaga ay nagmumula sa localStorage, kumplikadong pagbabago ng data, o pag-parse ng URL parameters. Tinatawag ng React ang initializer function nang isang beses lamang — sa pag-mount ng component, na nakatipid ng resources sa mga susunod na render. Kung walang lazy initialization, ang mamahaling expression ay kakalkulahin sa bawat render, kahit na ang resulta nito ay binabalewala.

FormHalimbawaKailan gagamitin
DirektauseState(0)Simpleng paunang halaga
LazyuseState(() => compute())Mamahaling paunang pagkalkula
Functional na settersetState(prev => prev + 1)Pag-update batay sa nauna
Direktang settersetState(newValue)Bagong halaga ay hindi nakadepende sa luma
jsx
// State ng object — gumawa ng bagong reference
const [user, setUser] = useState(() => {
    const saved = localStorage.getItem('user');
    return saved ? JSON.parse(saved) : null;
});

useState na may iba't ibang uri ng data

useState ay gumagana nang maayos sa mga primitive (numero, string, boolean) at reference type (array, object). Ngunit may mahalagang pagkakaiba: para sa mga primitive, nakikita ng React ang pagbabago batay sa halaga, para sa mga object at array — batay sa reference. Ang pag-mutate ng umiiral na object nang hindi gumagawa ng bago ay hindi magdudulot ng re-render, dahil ang reference ay nanatiling pareho.

Kapag nagtatrabaho sa mga object at array, laging gumawa ng bagong kopya na may binagong data. Para sa mga object gamitin ang spread syntax: setUser(prev => ({...prev, name: newName})). Para sa mga array — mga method na nagbabalik ng bagong array: filter, map, concat, o spread syntax para sa pagdaragdag ng mga elemento. Ang mga mutation method tulad ng push, pop, splice nang direkta hindi gagana — balewalain sila ng React dahil hindi nagbago ang reference sa array.

jsx
// ✅ Tama: hooks sa pinakamataas na antas
const [form, setForm] = useState({ name: '', email: '' });
const updateField = (field, value) =>
    setForm(prev => ({ ...prev, [field]: value }));

// ...
const [items, setItems] = useState([]);
const addItem = item =>
    setItems(prev => [item, ...prev]);

Mga patakaran sa paggamit ng hooks sa useState

Tulad ng lahat ng React hooks, ang useState ay sumusunod sa dalawang patakaran. Una: tawagin ang mga hooks lamang sa pinakamataas na antas ng component — hindi maaaring ilagay ang mga ito sa loob ng mga kondisyon, loop, o nested function. Tinitiyak nito na ang mga hooks ay tinatawag sa parehong pagkakasunud-sunod sa bawat render, na kritikal para sa panloob na naka-link na listahan ng React.

Ikalawang patakaran: tawagin ang mga hooks lamang mula sa mga functional React component o custom hooks. Huwag tawagin ang useState mula sa mga ordinaryong function, callback, o class component. Ang paglabag sa mga patakarang ito ay humahantong sa error na Invalid hook call, na nakikita ng React sa yugto ng pagpapatupad.

  • Hindi sa kondisyon — if (flag) { useState(0) } lumalabag sa pagkakasunud-sunod ng pagtawag ng hooks.
  • Hindi sa loop — for (...) { useState(0) } ginagawang hindi mahulaan ang pagkakasunud-sunod.
  • Hindi sa callback — useEffect(() => { useState(0) }, []) sisirain ang naka-link na listahan.
jsx
// ❌ Problema ng lumang closure
function GoodComponent() {
    const [count, setCount] = useState(0);
    const [name, setName] = useState('');
    // ✅ Naayos gamit ang functional na update
}

// luma na ang counter!
function BadComponent() {
    if (isLogged) {
        const [user, setUser] = useState(null);
    }
}

Mga karaniwang pagkakamali sa useState

Ang pinakakaraniwang pagkakamali — direktang mutation ng mga object at array sa halip na gumawa ng mga bagong reference. Nasanay ang mga developer sa mutable style mula sa class component, kung saan ang this.state.user.name = “Bagong pangalan” ay gumagana (kahit hindi inirerekomenda). Sa mga functional component, ang ganitong mutation ay binabalewala lamang: hindi nakikita ng React ang pagbabago ng reference at hindi iginuguhit muli ang component.

  • Mutation ng object — user.name = “Bago” sa halip na setUser({...user, name: “Bago”}).
  • Lumang closure — paggamit ng lumang halaga sa setter nang walang functional form.
  • Mga sobrang re-render — pagtawag ng setter na may parehong halaga (React 18 ay magre-render pa rin para sa primitives).
  • Pag-reset ng state — hindi sinasadyang pag-update ng key prop ng component, na nagre-mount muli nito.

Ang problema ng lumang closure (stale closure) ay nangyayari kapag ang callback na ipinasa sa useEffect o event handler ay “nahuhuli” ang lumang halaga ng state mula sa closure sa oras ng paggawa ng callback. Ang solusyon — gamitin ang functional form ng setter o isama ang mga kinakailangang halaga sa dependency array ng useEffect. Ayon sa React Documentation — Hooks FAQ (2025), ang mga lumang closure ay pangalawang pinakakaraniwang sanhi ng bugs sa hooks pagkatapos ng maling dependency array.

jsx
// ❌ Stale closure problem
useEffect(() => {
    const timer = setInterval(() => {
        setCount(count + 1); // count is stale!
    }, 1000);
    return () => clearInterval(timer);
}, []);

// ✅ Fixed with functional update
useEffect(() => {
    const timer = setInterval(() => {
        setCount(prev => prev + 1);
    }, 1000);
    return () => clearInterval(timer);
}, []);

Mga Madalas Itanong

Maaari bang gamitin ang useState para sa mga kumplikadong nested object?

Oo, ngunit may pag-iingat. Para sa malalim na nested object, ang bawat antas ay nangangailangan ng pagkopya sa pag-update: setState(prev => ({...prev, nested: {...prev.nested, key: newValue}})). Kung mayroon kang mga object na may tatlo o higit pang antas ng nesting, isaalang-alang ang Immer (library para sa imutable na pag-update) o hatiin ang state sa maraming useState para sa iba't ibang antas.

Ang useState ba ay asynchronous o synchronous?

useState ay asynchronous sa kahulugan na ang pagtawag ng setter ay hindi agad ina-update ang halaga. Inilalagay ng React ang update sa queue at isinasagawa ito sa susunod na render. Pagkatapos ng setCount(newValue), ang variable na count sa kasalukuyang function ay naglalaman pa rin ng lumang halaga. Ang bagong halaga ay magiging available lamang sa susunod na pagtawag ng component. Tinitiyak ng mekanismo ng batching na ang maraming pagtawag ay naka-grupo sa isang render.

Ano ang mangyayari kung ang useState ay tinawag sa labas ng component?

Ang React ay magtapon ng error na Invalid hook call. Ang mga hooks ay maaari lamang tawagin sa loob ng mga functional React component o custom hooks (mga function na ang pangalan ay nagsisimula sa use). Ang limitasyong ito ay naka-embed sa implementasyon ng mga hooks: ginagamit nila ang fiber tree ng component para mag-imbak ng state, at sa labas ng component ang tree na ito ay hindi available.

Kailan gagamitin ang useState at kailan ang useReducer?

useState ay angkop para sa simpleng independyenteng state (mga counter, input field, flag). useReducer ay mas mahusay kapag ang state ay isang kumplikadong object na may maraming field, ang update logic ay nakadepende sa uri ng aksyon, o ang susunod na state ay nangangailangan ng kumplikadong pagbabago. Praktikal na patakaran: kung mayroon kang higit sa tatlong magkakaugnay na state field — gamitin ang useReducer.

Bakit hindi agad ina-update ng useState ang halaga?

Ito ay ginawa para sa performance. Kung ang useState ay mag-a-update ng state nang synchronously, ang bawat pagtawag ng setter ay magdudulot ng agarang re-render, na hahantong sa maraming pag-redraw sa loob ng isang event handler. Ang batching, kung saan ang React ay nag-grupo ng mga update at nagsasagawa ng isang re-render, ay isang optimisasyon na ipinakilala noong React 16 at makabuluhang pinabuti sa React 18 gamit ang automatic batching.

Buod

  • useState — pangunahing React hook para sa pamamahala ng lokal na state sa mga functional component, nagbabalik ng [state, setter].
  • Imutabilidad — ang state ay hindi direktang ma-mutate; laging magpasa ng bagong halaga o gamitin ang functional form ng setter.
  • Lazy initialization — para sa mamahaling paunang pagkalkula magpasa ng function: useState(() => compute()).
  • Functional na setter — setState(prev => prev + 1) ginagarantiya ang kawastuhan sa naka-batch na mga update.
  • Batching — ang React ay nag-grupo ng maraming pagtawag ng setter sa isang re-render para sa optimisasyon.
  • Mga patakaran ng hooks — tawagin ang useState lamang sa pinakamataas na antas ng component, hindi sa kondisyon o loop.
  • Mga uri ng data — para sa mga object at array laging gumawa ng bagong reference sa pag-update.

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.

Pag-usapan ang proyekto

Basahin din