useState: vad är det, state-hook och syntax i React

Författare: IT Sectr Publicerad: 2026-07-04 Lästid: 9 min

useState — är en inbyggd React-hook som gör det möjligt för funktionella komponenter att hantera lokalt state utan att omvandlas till klasskomponenter. React 16.8 introducerade hooks, och useState blev den mest använda av dem, och ersatte this.state och this.setState från klassbaserade tillvägagångssättet. Enligt React Documentation (2025) använder över 80% av komponenterna i moderna React-applikationer useState för att hantera formulärdata, gränssnittsflaggor och räknare. Hooken returnerar en tupel bestående av det aktuella värdet och en setter-funktion som uppdaterar state och initierar en omrendering av komponenten.

Huvudpunkter

  • useState — hook för att hantera lokalt state i funktionella React-komponenter.
  • Tupel — returnerar ett par [värde, setter], där setter är funktionen som uppdaterar state.
  • Omrendering — anrop av setter initierar alltid en omritning av komponenten med det nya värdet.
  • Datatyper — useState fungerar med tal, strängar, arrayer, objekt och booleska värden.
  • Oföränderlighet — state kan inte muteras direkt, endast via setter-funktionen.

Vad är useState i React

useState — är den grundläggande React-hooken, tillagd i version 16.8, som ger funktionella komponenter möjlighet att lagra och ändra lokalt state. Innan hooks kom kunde state endast användas i klasskomponenter via this.state och this.setState, vilket gjorde funktionella komponenter enbart presentationsmässiga. useState tog bort denna begränsning och gjorde det möjligt att skriva hela applikationen med funktionella komponenter.

Hooken tar ett argument — startvärdet för state — och returnerar en array med två element. Det första elementet är det aktuella värdet av state, det andra är funktionen för att uppdatera det. React garanterar att setter-funktionen är stabil och inte förändras mellan renderingar, vilket möjliggör säker överföring till underordnade komponenter och användning i closures.

Enligt React DevTools Usage Survey (2024) används useState i 96% av React-applikationerna, vilket gör det till den mest utbredda hooken i ekosystemet. Även i applikationer som använder globalt state via Redux eller Zustand förblir lokalt state via useState den främsta mekanismen för UI-state-hantering — öppna modaler, värden på inmatningsfält, aktiva flikar.

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

Hur fungerar useState

Den interna mekanismen för useState bygger på Reacts fiber-nodsystem. Varje komponent i React representeras av en fiber-nod som lagrar den associerade listan av hooks i form av en länkad lista. När komponenten anropar useState skapar React en ny nod i denna lista och lagrar i den det aktuella state-värdet och en referens till uppdateringskön.

När setter-funktionen anropas uppdaterar React inte state omedelbart. Istället placerar den uppdateringen i kön (pending state queue), schemalägger en omrendering av komponenten och beräknar först under nästa rendering det nya state baserat på det gamla och tillämpade uppdateringar. Detta säkerställer batchhantering — om du i en händelsehanterare anropar setter tre gånger, grupperar React dem till en omrendering.

Enligt React Team — React 18 Working Group (2024) utökades automatisk batchhantering i React 18: nu grupperas state-uppdateringar inte bara i händelsehanterare, utan även i setTimeout, Promise-callbacks och inbyggda hanterare. Detta gav en prestandaökning på upp till 30% i scenarier med flera state-uppdateringar.

Funktionell state-uppdatering

När det nya state beror på det föregående, använd den funktionella formen av setter: setCount(prev => prev + 1). React skickar till funktionen det aktuella state-värdet vid tidpunkten för uppdateringens tillämpning, vilket garanterar korrekthet även vid batchade uppdateringar. Utan den funktionella formen kan setCount(count + 1) använda ett föråldrat värde om det anropas flera gånger i rad.

jsx
// Lazy initiering — körs endast en gång
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 för useState: deklaration och uppdatering

Grundläggande syntax för useState är ytterst koncis: const [state, setState] = useState(initialValue). Startvärdet används endast vid första renderingen; vid efterföljande renderingar ignorerar React det och returnerar det aktuella lagrade värdet. Om den initiala beräkningen kräver dyra operationer, skicka en initialiseringsfunktion: useState(() => computeExpensiveInitial()).

Lazy initiering (lazy initial state) är särskilt viktig när startvärdet kommer från localStorage, komplex datatransformering eller tolkning av URL-parametrar. React anropar initialiseringsfunktionen endast en gång — vid montering av komponenten, vilket sparar resurser vid efterföljande renderingar. Utan lazy initiering kommer det dyra uttrycket att beräknas vid varje rendering, även om dess resultat ignoreras.

FormExempelNär ska man använda
DirektuseState(0)Enkelt startvärde
LazyuseState(() => compute())Dyr initial beräkning
Funktionell settersetState(prev => prev + 1)Uppdatering baserad på föregående
Direkt settersetState(newValue)Nytt värde beror inte på gammalt
jsx
// Objekt state — skapa ny referens
const [user, setUser] = useState(() => {
    const saved = localStorage.getItem('user');
    return saved ? JSON.parse(saved) : null;
});

useState med olika datatyper

useState fungerar lika bra med primitiver (tal, strängar, boolean) och referenstyper (arrayer, objekt). Det finns dock en viktig skillnad: för primitiver upptäcker React förändringen baserat på värde, för objekt och arrayer — baserat på referens. Mutation av ett befintligt objekt utan att skapa ett nytt kommer inte att orsaka omrendering eftersom referensen förblev densamma.

När du arbetar med objekt och arrayer, skapa alltid en ny kopia med modifierad data. För objekt använd spread-syntax: setUser(prev => ({...prev, name: newName})). För arrayer — metoder som returnerar en ny array: filter, map, concat, eller spread-syntax för att lägga till element. Mutationsmetoder som push, pop, splice fungerar direkt inte — React ignorerar dem eftersom referensen till arrayen inte har ändrats.

jsx
// ✅ Korrekt: hooks på högsta nivån
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]);

Regler för användning av hooks med useState

Liksom alla React hooks följer useState två regler. För det första: anropa hooks endast på den högsta nivån av komponenten — de kan inte placeras i villkor, loopar eller nästlade funktioner. Detta garanterar att hooks anropas i samma ordning vid varje rendering, vilket är avgörande för Reacts interna länkade lista.

Den andra regeln: anropa hooks endast från funktionella React-komponenter eller anpassade hooks. Anropa inte useState från vanliga funktioner, callbacks eller klasskomponenter. Brott mot dessa regler leder till felet Invalid hook call, som React upptäcker under körningsfasen.

  • Inte i villkor — if (flag) { useState(0) } bryter mot anropsordningen för hooks.
  • Inte i loopar — for (...) { useState(0) } gör ordningen oförutsägbar.
  • Inte i callbacks — useEffect(() => { useState(0) }, []) kommer att förstöra den länkade listan.
jsx
// ❌ Problem med föråldrad closure
function GoodComponent() {
    const [count, setCount] = useState(0);
    const [name, setName] = useState('');
    // ✅ Åtgärdat med funktionell uppdatering
}

// räknaren är föråldrad!
function BadComponent() {
    if (isLogged) {
        const [user, setUser] = useState(null);
    }
}

Vanliga misstag med useState

Det vanligaste misstaget — direkt mutation av objekt och arrayer istället för att skapa nya referenser. Utvecklare har vant sig vid den mutabla stilen från klasskomponenter, där this.state.user.name = “Nytt namn” fungerade (även om det inte rekommenderades). I funktionella komponenter ignoreras sådan mutation helt enkelt: React ser inte referensändringen och ritar inte om komponenten.

  • Objektmutation — user.name = “Nytt” istället för setUser({...user, name: “Nytt”}).
  • Föråldrad closure — användning av föråldrat värde i setter utan funktionell form.
  • Onödiga omrenderingar — anropa setter med samma värde (React 18 renderar ändå för primitiver).
  • Återställning av state — oavsiktlig uppdatering av komponentens key-prop, vilket återmonterar den.

Problemet med föråldrad closure (stale closure) uppstår när en callback som skickas till useEffect eller händelsehanterare ”fångar” ett föråldrat state-värde från closuren vid tidpunkten för skapandet av callbacken. Lösningen — använd den funktionella formen av setter eller inkludera nödvändiga värden i useEffect-beroendematrisen. Enligt React Documentation — Hooks FAQ (2025) är föråldrade closures den näst vanligaste orsaken till buggar i hooks efter felaktig beroendematris.

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);
}, []);

Vanliga frågor

Kan useState användas för komplexa nästlade objekt?

Ja, men med försiktighet. För djupt nästlade objekt kräver varje nivå kopiering vid uppdatering: setState(prev => ({...prev, nested: {...prev.nested, key: newValue}})). Om du har objekt med tre eller fler nivåer av nästling, överväg Immer (bibliotek för oföränderlig uppdatering) eller dela upp state i flera useState för olika nivåer.

Är useState asynkron eller synkron?

useState är asynkron i den meningen att anrop av setter inte uppdaterar värdet omedelbart. React placerar uppdateringen i kön och utför den vid nästa rendering. Efter setCount(newValue) innehåller variabeln count i den aktuella funktionen fortfarande det gamla värdet. Det nya värdet kommer att vara tillgängligt först vid nästa anrop av komponenten. Batchhanteringsmekanismen garanterar att flera anrop grupperas i en rendering.

Vad händer om useState anropas utanför komponenten?

React kommer att kasta felet Invalid hook call. Hooks kan endast anropas inuti funktionella React-komponenter eller anpassade hooks (funktioner vars namn börjar med use). Denna begränsning är inbyggd i implementeringen av hooks: de använder komponentens fiber-träd för att lagra state, och utanför komponenten är detta träd inte tillgängligt.

När ska man använda useState och när useReducer?

useState passar för enkla oberoende states (räknare, inmatningsfält, flaggor). useReducer är bättre när state är ett komplext objekt med flera fält, uppdateringslogiken beror på åtgärdstypen eller nästa state kräver en komplex transformation. Praktisk regel: om du har fler än tre relaterade state-fält — använd useReducer.

Varför uppdaterar useState inte värdet omedelbart?

Detta görs för prestanda. Om useState uppdaterade state synkront skulle varje setter-anrop orsaka omedelbar omrendering, vilket skulle leda till flera omritningar inom en händelsehanterare. Batchhantering, där React grupperar uppdateringar och utför en omrendering, är en optimering som introducerades redan i React 16 och förbättrades avsevärt i React 18 med automatisk batchhantering.

Sammanfattning

  • useState — grundläggande React-hook för att hantera lokalt state i funktionella komponenter, returnerar [state, setter].
  • Oföränderlighet — state kan inte muteras direkt; skicka alltid ett nytt värde eller använd den funktionella formen av setter.
  • Lazy initiering — för dyra initiala beräkningar skicka en funktion: useState(() => compute()).
  • Funktionell setter — setState(prev => prev + 1) garanterar korrekthet vid batchade uppdateringar.
  • Batchhantering — React grupperar flera setter-anrop till en omrendering för optimering.
  • Hook-regler — anropa useState endast på den högsta nivån av komponenten, inte i villkor eller loopar.
  • Datatyper — för objekt och arrayer, skapa alltid en ny referens vid uppdatering.

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också