useState: τι είναι, hook κατάστασης και σύνταξη στο React

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-07-04 Χρόνος ανάγνωσης: 9 λεπ

useState — είναι ένα ενσωματωμένο hook του React που επιτρέπει στα functional components να διαχειρίζονται τοπική κατάσταση χωρίς μετατροπή σε class components. Το React 16.8 εισήγαγε τα hooks, και το useState έγινε το πιο χρησιμοποιούμενο από αυτά, αντικαθιστώντας το this.state και το this.setState από την προσέγγιση κλάσεων. Σύμφωνα με React Documentation (2025), πάνω από 80% των components σε σύγχρονες εφαρμογές React χρησιμοποιούν το useState για τη διαχείριση δεδομένων φορμών, σημαιών διεπαφής και μετρητών. Το hook επιστρέφει μια πλειάδα με την τρέχουσα τιμή και μια συνάρτηση setter που ενημερώνει την κατάσταση και προκαλεί εκ νέου απόδοση του component.

Βασικά σημεία

  • useState — hook για διαχείριση τοπικής κατάστασης σε functional components React.
  • Πλειάδα — επιστρέφει ένα ζεύγος [τιμή, setter], όπου setter είναι η συνάρτηση ενημέρωσης κατάστασης.
  • Εκ νέου απόδοση — η κλήση του setter προκαλεί πάντα επανασχεδίαση του component με τη νέα τιμή.
  • Τύποι δεδομένων — το useState λειτουργεί με αριθμούς, συμβολοσειρές, πίνακες, αντικείμενα και boolean τιμές.
  • Αμεταβλητότητα — η κατάσταση δεν μπορεί να μεταβληθεί άμεσα, μόνο μέσω της συνάρτησης setter.

Τι είναι το useState στο React

useState — είναι το θεμελιώδες hook του React, που προστέθηκε στην έκδοση 16.8, το οποίο δίνει στα functional components τη δυνατότητα να αποθηκεύουν και να αλλάζουν τοπική κατάσταση. Πριν την εμφάνιση των hooks, η κατάσταση μπορούσε να χρησιμοποιηθεί μόνο σε class components μέσω του this.state και this.setState, καθιστώντας τα functional components αποκλειστικά παρουσιαστικά. Το useState εξάλειψε αυτόν τον περιορισμό, επιτρέποντας τη συγγραφή ολόκληρης της εφαρμογής σε functional components.

Το hook δέχεται ένα όρισμα — την αρχική τιμή της κατάστασης — και επιστρέφει έναν πίνακα δύο στοιχείων. Το πρώτο στοιχείο είναι η τρέχουσα τιμή της κατάστασης, το δεύτερο είναι η συνάρτηση για την ενημέρωσή της. Το React εγγυάται ότι η συνάρτηση setter είναι σταθερή και δεν αλλάζει μεταξύ των αποδόσεων, επιτρέποντας την ασφαλή μεταβίβασή της σε child components και τη χρήση της σε closures.

Σύμφωνα με το React DevTools Usage Survey (2024), το useState χρησιμοποιείται στο 96% των εφαρμογών React, καθιστώντας το το πιο διαδεδομένο hook στο οικοσύστημα. Ακόμη και σε εφαρμογές που χρησιμοποιούν καθολική κατάσταση μέσω Redux ή Zustand, η τοπική κατάσταση μέσω του useState παραμένει ο κύριος μηχανισμός διαχείρισης κατάστασης UI — ανοιχτά modals, τιμές πεδίων εισόδου, ενεργές καρτέλες.

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

Πώς λειτουργεί το useState

Ο εσωτερικός μηχανισμός του useState βασίζεται στο σύστημα fiber κόμβων του React. Κάθε component στο React αντιπροσωπεύεται από έναν fiber κόμβο που αποθηκεύει τη σχετιζόμενη λίστα hooks με τη μορφή συνδεδεμένης λίστας. Όταν το component καλεί το useState, το React δημιουργεί έναν νέο κόμβο σε αυτή τη λίστα και αποθηκεύει σε αυτόν την τρέχουσα τιμή κατάστασης και μια αναφορά στην ουρά ενημερώσεων.

Κατά την κλήση της συνάρτησης setter, το React δεν ενημερώνει αμέσως την κατάσταση. Αντίθετα, τοποθετεί την ενημέρωση σε ουρά (pending state queue), προγραμματίζει την εκ νέου απόδοση του component και μόνο κατά την επόμενη απόδοση υπολογίζει τη νέα κατάσταση βάσει της παλιάς και των εφαρμοσμένων ενημερώσεων. Αυτό εξασφαλίζει ομαδοποίηση (batching) — αν σε έναν χειριστή συμβάντος καλέσετε τον setter τρεις φορές, το React τις ομαδοποιεί σε μία εκ νέου απόδοση.

Σύμφωνα με το React Team — React 18 Working Group (2024), η αυτόματη ομαδοποίηση επεκτάθηκε στο React 18: τώρα οι ενημερώσεις κατάστασης ομαδοποιούνται όχι μόνο σε χειριστές συμβάντων, αλλά και σε setTimeout, Promise callbacks και native χειριστές. Αυτό έφερε αύξηση απόδοσης έως 30% σε σενάρια με πολλαπλές ενημερώσεις κατάστασης.

Λειτουργική ενημέρωση κατάστασης

Όταν η νέα κατάσταση εξαρτάται από την προηγούμενη, χρησιμοποιήστε τη λειτουργική μορφή του setter: setCount(prev => prev + 1). Το React μεταβιβάζει στη συνάρτηση την πραγματική τιμή κατάστασης τη στιγμή εφαρμογής της ενημέρωσης, εξασφαλίζοντας ορθότητα ακόμη και σε ομαδοποιημένες ενημερώσεις. Χωρίς λειτουργική μορφή, το setCount(count + 1) μπορεί να χρησιμοποιήσει παρωχημένη τιμή αν κληθεί πολλές φορές στη σειρά.

jsx
// Τεμπέλης αρχικοποίηση — εκτελείται μόνο μία φορά
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)

Σύνταξη του useState: δήλωση και ενημέρωση

Η βασική σύνταξη του useState είναι εξαιρετικά συνοπτική: const [state, setState] = useState(initialValue). Η αρχική τιμή χρησιμοποιείται μόνο στην πρώτη απόδοση· σε επόμενες αποδόσεις το React την αγνοεί και επιστρέφει την τρέχουσα αποθηκευμένη τιμή. Εάν ο αρχικός υπολογισμός απαιτεί δαπανηρές λειτουργίες, μεταβιβάστε μια συνάρτηση αρχικοποίησης: useState(() => computeExpensiveInitial()).

Η τεμπέλης αρχικοποίηση (lazy initial state) είναι ιδιαίτερα σημαντική όταν η αρχική τιμή προέρχεται από το localStorage, σύνθετο μετασχηματισμό δεδομένων ή ανάλυση παραμέτρων URL. Το React καλεί τη συνάρτηση αρχικοποίησης μόνο μία φορά — κατά την τοποθέτηση του component, εξοικονομώντας πόρους σε επόμενες αποδόσεις. Χωρίς τεμπέλη αρχικοποίηση, η δαπανηρή έκφραση θα υπολογίζεται σε κάθε απόδοση, ακόμη κι αν το αποτέλεσμά της αγνοείται.

ΜορφήΠαράδειγμαΠότε να χρησιμοποιείται
ΆμεσηuseState(0)Απλή αρχική τιμή
ΤεμπέληςuseState(() => compute())Δαπανηρός αρχικός υπολογισμός
Λειτουργικός settersetState(prev => prev + 1)Ενημέρωση βάσει προηγούμενης
Άμεσος settersetState(newValue)Νέα τιμή δεν εξαρτάται από παλιά
jsx
// Κατάσταση αντικειμένου — δημιουργήστε νέα αναφορά
const [user, setUser] = useState(() => {
    const saved = localStorage.getItem('user');
    return saved ? JSON.parse(saved) : null;
});

useState με διαφορετικούς τύπους δεδομένων

Το useState λειτουργεί εξίσου καλά με πρωτογενείς τύπους (αριθμοί, συμβολοσειρές, boolean) και τύπους αναφοράς (πίνακες, αντικείμενα). Υπάρχει όμως μια σημαντική διαφορά: για πρωτογενείς τύπους, το React ανιχνεύει την αλλαγή βάσει τιμής, για αντικείμενα και πίνακες — βάσει αναφοράς. Η μετάλλαξη ενός υπάρχοντος αντικειμένου χωρίς δημιουργία νέου δεν θα προκαλέσει εκ νέου απόδοση, επειδή η αναφορά παραμένει ίδια.

Κατά την εργασία με αντικείμενα και πίνακες, δημιουργείτε πάντα ένα νέο αντίγραφο με τροποποιημένα δεδομένα. Για αντικείμενα χρησιμοποιήστε σύνταξη spread: setUser(prev => ({...prev, name: newName})). Για πίνακες — μεθόδους που επιστρέφουν νέο πίνακα: filter, map, concat, ή σύνταξη spread για προσθήκη στοιχείων. Οι μέθοδοι μετάλλαξης όπως push, pop, splice άμεσα δεν θα λειτουργήσουν — το React θα τις αγνοήσει, επειδή η αναφορά στον πίνακα δεν άλλαξε.

jsx
// ✅ Σωστό: hooks στο ανώτατο επίπεδο
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]);

Κανόνες χρήσης hooks με το useState

Όπως όλα τα hooks του React, το useState υπακούει σε δύο κανόνες. Πρώτον: καλείτε τα hooks μόνο στο ανώτατο επίπεδο του component — δεν μπορούν να τοποθετηθούν εντός συνθηκών, βρόχων ή ένθετων συναρτήσεων. Αυτό εγγυάται ότι τα hooks καλούνται με την ίδια σειρά σε κάθε απόδοση, κάτι που είναι κρίσιμο για την εσωτερική συνδεδεμένη λίστα του React.

Δεύτερος κανόνας: καλείτε τα hooks μόνο από functional components React ή custom hooks. Μην καλείτε το useState από συνηθισμένες συναρτήσεις, callbacks ή class components. Η παραβίαση αυτών των κανόνων οδηγεί στο σφάλμα Invalid hook call, το οποίο το React εντοπίζει κατά τη φάση εκτέλεσης.

  • Όχι σε συνθήκες — if (flag) { useState(0) } παραβιάζει τη σειρά κλήσης των hooks.
  • Όχι σε βρόχους — for (...) { useState(0) } καθιστά τη σειρά απρόβλεπτη.
  • Όχι σε callbacks — useEffect(() => { useState(0) }, []) θα σπάσει τη συνδεδεμένη λίστα.
jsx
// ❌ Πρόβλημα παρωχημένου closure
function GoodComponent() {
    const [count, setCount] = useState(0);
    const [name, setName] = useState('');
    // ✅ Διορθώθηκε με λειτουργική ενημέρωση
}

// ο μετρητής είναι παρωχημένος!
function BadComponent() {
    if (isLogged) {
        const [user, setUser] = useState(null);
    }
}

Συνηθισμένα λάθη με το useState

Το πιο συνηθισμένο λάθος — άμεση μετάλλαξη αντικειμένων και πινάκων αντί για δημιουργία νέων αναφορών. Οι προγραμματιστές έχουν συνηθίσει στο μεταβλητό στυλ από τα class components, όπου το this.state.user.name = “Νέο όνομα” λειτουργούσε (αν και δεν συνιστάται). Στα functional components, μια τέτοια μετάλλαξη απλώς αγνοείται: το React δεν βλέπει την αλλαγή αναφοράς και δεν επανασχεδιάζει το component.

  • Μετάλλαξη αντικειμένου — user.name = “Νέο” αντί για setUser({...user, name: “Νέο”}).
  • Παρωχημένο closure — χρήση παρωχημένης τιμής σε setter χωρίς λειτουργική μορφή.
  • Περιττές εκ νέου αποδόσεις — κλήση setter με την ίδια τιμή (το React 18 θα αποδώσει ούτως ή άλλως για πρωτογενή).
  • Επαναφορά κατάστασης — ακούσια ενημέρωση του key prop του component, που το τοποθετεί ξανά.

Το πρόβλημα παρωχημένου closure (stale closure) προκύπτει όταν ένα callback που μεταβιβάζεται σε useEffect ή χειριστή συμβάντος “συλλαμβάνει” μια παρωχημένη τιμή κατάστασης από το closure τη στιγμή δημιουργίας του callback. Η λύση — χρήση της λειτουργικής μορφής του setter ή συμπερίληψη των απαραίτητων τιμών στον πίνακα εξαρτήσεων του useEffect. Σύμφωνα με το React Documentation — Hooks FAQ (2025), τα παρωχημένα closures είναι η δεύτερη πιο συχνή αιτία σφαλμάτων στα hooks μετά από τον εσφαλμένο πίνακα εξαρτήσεων.

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

Συχνές Ερωτήσεις

Μπορεί να χρησιμοποιηθεί το useState για σύνθετα ένθετα αντικείμενα;

Ναι, αλλά με προσοχή. Για βαθιά ένθετα αντικείμενα, κάθε επίπεδο απαιτεί αντιγραφή κατά την ενημέρωση: setState(prev => ({...prev, nested: {...prev.nested, key: newValue}})). Αν έχετε αντικείμενα με τρία ή περισσότερα επίπεδα ένθεσης, εξετάστε το Immer (βιβλιοθήκη για αμετάβλητη ενημέρωση) ή χωρίστε την κατάσταση σε πολλά useState για διαφορετικά επίπεδα.

Το useState είναι ασύγχρονο ή σύγχρονο;

Το useState είναι ασύγχρονο με την έννοια ότι η κλήση του setter δεν ενημερώνει αμέσως την τιμή. Το React τοποθετεί την ενημέρωση σε ουρά και την εκτελεί κατά την επόμενη απόδοση. Μετά το setCount(newValue), η μεταβλητή count στην τρέχουσα συνάρτηση εξακολουθεί να περιέχει την παλιά τιμή. Η νέα τιμή θα είναι διαθέσιμη μόνο στην επόμενη κλήση του component.

Τι συμβαίνει αν το useState κληθεί εκτός component;

Το React θα πετάξει το σφάλμα Invalid hook call. Τα hooks μπορούν να κληθούν μόνο εντός functional components React ή custom hooks (συναρτήσεις των οποίων το όνομα αρχίζει με use). Αυτός ο περιορισμός είναι ενσωματωμένος στην υλοποίηση των hooks: χρησιμοποιούν το δέντρο fiber του component για αποθήκευση κατάστασης, και εκτός component αυτό το δέντρο δεν είναι διαθέσιμο.

Πότε να χρησιμοποιώ useState και πότε useReducer;

Το useState είναι κατάλληλο για απλές ανεξάρτητες καταστάσεις (μετρητές, πεδία εισόδου, σημαίες). Το useReducer είναι καλύτερο όταν η κατάσταση είναι ένα σύνθετο αντικείμενο με πολλαπλά πεδία, η λογική ενημέρωσης εξαρτάται από τον τύπο ενέργειας ή η επόμενη κατάσταση απαιτεί σύνθετο μετασχηματισμό. Πρακτικός κανόνας: αν έχετε περισσότερα από τρία συσχετιζόμενα πεδία κατάστασης — χρησιμοποιήστε useReducer.

Γιατί το useState δεν ενημερώνει την τιμή αμέσως;

Αυτό γίνεται για απόδοση. Αν το useState ενημέρωνε την κατάσταση σύγχρονα, κάθε κλήση setter θα προκαλούσε άμεση εκ νέου απόδοση, οδηγώντας σε πολλαπλές επανασχεδιάσεις εντός ενός χειριστή συμβάντος. Η ομαδοποίηση, όπου το React ομαδοποιεί τις ενημερώσεις και εκτελεί μία εκ νέου απόδοση, είναι μια βελτιστοποίηση που εισήχθη ήδη στο React 16 και βελτιώθηκε σημαντικά στο React 18 με αυτόματη ομαδοποίηση.

Σύνοψη

  • useState — το βασικό hook React για διαχείριση τοπικής κατάστασης σε functional components, επιστρέφοντας [state, setter].
  • Αμεταβλητότητα — η κατάσταση δεν μπορεί να μεταβληθεί άμεσα· να μεταβιβάζετε πάντα νέα τιμή ή να χρησιμοποιείτε τη λειτουργική μορφή του setter.
  • Τεμπέλης αρχικοποίηση — για δαπανηρούς αρχικούς υπολογισμούς μεταβιβάστε συνάρτηση: useState(() => compute()).
  • Λειτουργικός setter — το setState(prev => prev + 1) εγγυάται ορθότητα σε ομαδοποιημένες ενημερώσεις.
  • Ομαδοποίηση — το React ομαδοποιεί πολλαπλές κλήσεις setter σε μία εκ νέου απόδοση για βελτιστοποίηση.
  • Κανόνες hooks — καλείτε το useState μόνο στο ανώτατο επίπεδο του component, όχι σε συνθήκες ή βρόχους.
  • Τύποι δεδομένων — για αντικείμενα και πίνακες δημιουργείτε πάντα νέα αναφορά κατά την ενημέρωση.

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης