The useState hook - Ένας ολοκληρωμένος οδηγός PlatoBlockchain Data Intelligence. Κάθετη αναζήτηση. Ολα συμπεριλαμβάνονται.

The useState hook – Ένας περιεκτικός οδηγός

Τι είναι κράτος;

Πριν βουτήξουμε βαθιά στο useState hook ας καταλάβουμε πρώτα τον όρο κατάσταση.

Η κατάσταση αντιπροσωπεύει πληροφορίες για κάτι σε μια δεδομένη χρονική στιγμή.

Για παράδειγμα, ας εξετάσουμε ένα πλαίσιο κειμένου.

Αρχικά, δεν υπάρχει τίποτα μέσα σε αυτό το πλαίσιο κειμένου, επομένως είναι η κατάστασή του άδειο. Ας υποθέσουμε ότι ξεκινάτε να πληκτρολογείτε Hello μέσα σε αυτό, για κάθε πάτημα πλήκτρου η κατάσταση του πλαισίου κειμένου θα αλλάζει. Στην αρχή θα είναι "H", μετά "He", μετά "Hel" και ούτω καθεξής μέχρι να γίνει "Hello".

Επίσης, παρατηρήστε ότι καθώς πληκτρολογείτε, δεν χάνετε την προηγούμενη τιμή. Εάν πατήσετε το "H" και στη συνέχεια το "e", θα λάβετε "He" και όχι μόνο "e". Με άλλα λόγια, μπορείτε να σκεφτείτε το κράτος ως το μνήμη του πλαισίου κειμένου.

Η ανάγκη για κατάσταση σε ένα στοιχείο React.

Ας το καταλάβουμε αυτό με τη βοήθεια ενός παραδείγματος.

Codesanbox χωρίς κατάσταση

Εδώ έχουμε ένα ClickCounter στοιχείο που εμφανίζει πόσες φορές έγινε κλικ στο κουμπί Αύξηση.

Χρησιμοποιούμε ένα τοπική μεταβλητή "μετρητής" για να κρατήσετε τον αριθμό των κλικ.

Κάθε φορά που κάνουμε κλικ στο κουμπί Αύξηση, handleClick θα γίνει επίκληση της λειτουργίας. Αυτή η συνάρτηση θα αυξήσει την τιμή του μετρητή κατά 1 και θα καταγράψει επίσης την τιμή στην κονσόλα.

Συνεχίστε, κάντε κλικ στο κουμπί Προσαύξηση στην προεπισκόπηση του CodeSandbox.

Δεν έγινε τίποτα?

Λοιπόν η λογική μας φαίνεται να είναι σωστή. Η τιμή που καταγράφεται στην κονσόλα (CodeSandbox) ενημερώνεται σωστά κάθε φορά που κάνουμε κλικ, αλλά γιατί αυτή η ενημέρωση δεν αντικατοπτρίζεται στη διεπαφή χρήστη;

Αυτό οφείλεται στον τρόπο που λειτουργεί το React.

  • Οι αλλαγές σε τοπικές μεταβλητές δεν ενεργοποιούν εκ νέου απόδοση.
  • Κατά τη διάρκεια μιας εκ νέου απόδοσης, ένα στοιχείο δημιουργείται από την αρχή, δηλαδή η συνάρτηση ενός στοιχείου (σε αυτό το παράδειγμα είναι η συνάρτηση ClickCounter) εκτελείται ξανά. Εφόσον οι μεταβλητές (για παράδειγμα, μετρητής) είναι τοπικές στη συνάρτηση, οι προηγούμενες τιμές τους χάνονται.

Πώς λοιπόν κάνουμε το στοιχείο να θυμάται τις τιμές μεταξύ των αποδόσεων;

Ναι, σωστά κατάλαβες! Αυτό το κάνουμε με τη βοήθεια του χρησιμοποιήστε το κράτος άγκιστρο.

Το άγκιστρο useState

Το άγκιστρο useState παρέχει μηχανισμούς για τη διατήρηση της κατάστασης και την ενεργοποίηση μιας εκ νέου απόδοσης.

Ας δούμε τη χρήση του.

import React, { useState } from "react";
const state = useState(initialValue);

// OR

const state = React.useState(initialValue);

Το άγκιστρο useState επιστρέφει έναν πίνακα που περιέχει δύο στοιχεία:

  • A μεταβλητή κατάστασης που διατηρεί τις αξίες του κατά την επαναπόδοση. Η αρχική τιμή που μεταβιβάστηκε στο useState εκχωρείται στη μεταβλητή κατάσταση κατά την πρώτη απόδοση.
  • A λειτουργία ρυθμιστή που ενημερώνει τη μεταβλητή κατάστασης και επίσης ενεργοποιεί μια εκ νέου απόδοση.
const state = useState(0);
const data = state[0];
const setData = state[1];

Χρησιμοποιώντας αποδιάρθρωση συστοιχίας , μπορούμε να αναδιατυπώσουμε τις παραπάνω δηλώσεις σε μία μόνο πρόταση, όπως φαίνεται παρακάτω:

const [data, setData] = useState(0);

Η αρχική τιμή που μεταβιβάστηκε στο useState χρησιμοποιείται μόνο κατά την πρώτη απόδοση. Για τις εκ νέου αποδόσεις, αγνοείται.

Μετρητής με useState

Τώρα, ας ενημερώσουμε το προηγούμενο παράδειγμα μετρητή για να συμπεριλάβουμε το άγκιστρο useState.

  • Εφόσον χρειαζόμαστε την τιμή μετρητή μεταξύ των re-renders, ας τη μετατρέψουμε σε κατάσταση.
const [counter, setCounter] = useState(0);
  • Κλήση setCounter μέσα στη συνάρτηση handleClick.
const handleClick = () => {
  setCounter(counter + 1);
  console.log(`%c Counter:${counter}`, "color:green");
};

Η συνάρτηση setCounter θα ενημερώσει την τιμή του μετρητή κατά 1 και θα ενεργοποιήσει μια εκ νέου απόδοση. Όταν η συνάρτηση του στοιχείου καλείται σε εκ νέου απόδοση, η μεταβλητή κατάστασης που επιστρέφεται από το useState θα έχει την ενημερωμένη τιμή.

Δοκιμάστε το CodeSandbox με τον ενημερωμένο κωδικό. Κάντε κλικ στο κουμπί Increment και δείτε τη μαγεία του useState σε δράση.

Codesanbox με useState

Μπορείτε να επαληθεύσετε ότι σε μια εκ νέου απόδοση, το λειτουργικό στοιχείο ClickCounter καλείται ξανά προβάλλοντας τα αρχεία καταγραφής της κονσόλας. Το αρχείο καταγραφής "ClickCounter start" που προστίθεται στην αρχή του στοιχείου θα καταγράφεται σε κάθε απόδοση.

πρώτη απόδοση

εκ νέου απόδοση

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

Ας υποθέσουμε ότι θέλουμε να αυξήσουμε την τιμή του μετρητή κατά 4 σε κάθε κλικ.

const handleClick = () => {
  setCounter(counter + 1);
    setCounter(counter + 1);
    setCounter(counter + 1);
    setCounter(counter + 1);
    console.log(`%c Counter:${counter}`, "color:green");
    };

Ας υποθέσουμε ότι η αρχική τιμή του μετρητή είναι 0. Τι περιμένετε να δείτε μόλις κάνετε κλικ στο κουμπί;

Χωρίς λειτουργία ενημέρωσης

Περιμένατε το μέτρημα να είναι 4 σωστά; Αλλά γιατί βλέπετε 1;

α) Κάθε απόδοση συνδέεται με μια κατάσταση. Η τιμή αυτής της κατάστασης παραμένει κλειδωμένη για τη διάρκεια ζωής αυτής της απόδοσης.

Σημειώστε ότι το αρχείο καταγραφής μέσα στη συνάρτηση handleClick εκτυπώνει την τιμή του μετρητή ως 0.

Ανεξάρτητα από το πόσες φορές καλέσετε τη μέθοδο setCounter, η τιμή του μετρητή παραμένει η ίδια.

const handleClick = () => {
  setCounter(counter + 1);
    setCounter(counter + 1);
    setCounter(counter + 1);
    setCounter(counter + 1);
    console.log(`%c Counter:${counter}`, "color:green");
    };
β) Μέχρι να εκτελεστεί όλος ο κώδικας μέσα σε ένα πρόγραμμα χειρισμού συμβάντων, το React δεν θα ενεργοποιήσει μια εκ νέου απόδοση.

Για αυτόν τον λόγο, κάθε κλήση setCounter δεν ενεργοποιεί μια μεμονωμένη απόδοση. Αντίθετα, το React προσθέτει αυτές τις συναρτήσεις ρυθμιστή σε μια ουρά. Τους εκτελεί με τη σειρά που τέθηκαν στην ουρά. Οι ενημερώσεις που γίνονται στην κατάσταση μετά την εκτέλεση όλων των δηλώσεων αντικατοπτρίζονται στην επόμενη απόδοση. Αυτή η ουρά πολλαπλών ενημερώσεων κατάστασης είναι γνωστή ως δοσοληψία. Επιτρέπει στο React να είναι πιο αποδοτικό.

Επομένως, εδώ παίρνουμε ένα μόνο render αντί για 4 διαφορετικά renders.

Αυτό το παράδειγμα είναι απλό και μπορείτε να διορθώσετε αυτό το πρόβλημα ενημερώνοντας τον κώδικα όπως φαίνεται παρακάτω:

const handleClick = () => {
setCounter(counter + 4);
    console.log(`%c Counter:${counter}`, "color:green");
    };

Τι θα γινόταν όμως αν είχατε μια περίπτωση χρήσης όπου θέλατε να ενημερώσετε την κατάσταση πολλές φορές πριν από την επόμενη απόδοση.

Εκεί είναι που το _ ανανεωτής _ η λειτουργία είναι χρήσιμη.

Μπορούμε να αναδιαμορφώσουμε το προηγούμενο παράδειγμα με τη συνάρτηση updater ως εξής:

const handleClick = () => {
  setCounter(prevCounter => prevCounter + 1);
    setCounter(prevCounter => prevCounter + 1);
    setCounter(prevCounter => prevCounter + 1);
    setCounter(prevCounter => prevCounter + 1);
    console.log(`%c Counter:${counter}`, "color:green");
    };

Εδώ prevCounter ⇒ prevCounter + 1 αντιπροσωπεύει τη λειτουργία ενημέρωσης.

Όπως εξηγήθηκε προηγουμένως, αυτές οι δηλώσεις ενημέρωσης βρίσκονται επίσης στην ουρά (ομαδική).

Η συνάρτηση ενημέρωσης λαμβάνει μια κατάσταση σε εκκρεμότητα/προηγούμενη, την οποία χρησιμοποιεί για τον υπολογισμό της επόμενης κατάστασης.

Μαζική λειτουργία ενημέρωσης

Παρακάτω είναι το CodeSandbox με την προσθήκη της λειτουργίας ενημέρωσης. Δοκιμάστε να κάνετε κλικ στο κουμπί αύξησης.

Λειτουργία ενημέρωσης sandbox

Λειτουργία αρχικοποιητή

Ρίξτε μια ματιά στο παρακάτω παράδειγμα. Εδώ καλούμε τη συνάρτηση getItems για να λάβουμε την αρχική τιμή για την κατάσταση.

import React from "react";
import { useState } from "react";
function ListItems() { 
  const getItems = () => { 
    console.log(`%c getItems called`, "color:hotpink");
    	return Array(50).fill(0); 
    }; 
  const [items, setItems] = useState(getItems()); 
    
    return ( 
    	<div className="card">
        <ul> {items.map((item, index) => 
        	( <li key={index}>Item {index + 1}		</li>))} 
        </ul> <button onClick={() => setItems([...items, 0])}>Add Item</button> 	</div> );
} 
export default ListItems;

Αυτή η συνάρτηση δημιουργεί έναν πίνακα με μέγεθος 50 και γεμίζει τον πίνακα με μηδενικά. Ανατρέξτε στην παρακάτω εικόνα.

Πίνακας γεμάτος με 50 μηδενικά

Στη συνέχεια, αυτά τα στοιχεία εμφανίζονται στην οθόνη.

Όλα δείχνουν να είναι καλά, αλλά έχουμε ένα πρόβλημα εδώ.

Κάντε κλικ στο Πρόσθεσε είδος κουμπί (βρίσκεται μετά τη λίστα των στοιχείων) για να προσθέσετε ένα νέο στοιχείο στη λίστα. Παρατηρήστε τα ημερολόγια.

Χωρίς λειτουργία αρχικοποιητή

Βλέπετε το πρόβλημα εδώ;

Το αρχείο καταγραφής "getItems call" προστίθεται στην κονσόλα κάθε φορά που προσθέτετε ένα στοιχείο. Αυτό σημαίνει ότι αυτή η συνάρτηση καλείται σε κάθε απόδοση.

Θυμηθείτε ότι το useState αγνοεί την αρχική τιμή που του μεταβιβάστηκε μετά την πρώτη απόδοση, αλλά εδώ η αρχική τιμή εξακολουθεί να υπολογίζεται εκ νέου. Αυτό μπορεί να είναι ακριβό εάν δημιουργούμε μεγάλους πίνακες ή εκτελούμε μεγάλους υπολογισμούς.

Μπορούμε να λύσουμε αυτό το θέμα περνώντας getItems ως _ αρχικοποιητή _ λειτουργία.

Τώρα, ας κάνουμε μια μικρή αλλαγή στον κώδικα.

const [items, setItems] = useState(getItems);

Με λειτουργία αρχικοποιητή

Δείτε το παράθυρο της κονσόλας στο CodeSandbox. Σημειώστε ότι το αρχείο καταγραφής "getItems call" εκτυπώνεται μόνο στην πρώτη απόδοση. Όταν προστίθενται επόμενα στοιχεία, αυτό το αρχείο καταγραφής δεν υπάρχει.

Αν και δεν υπάρχει οπτική διαφορά μεταξύ των δύο παραδειγμάτων, όσον αφορά την απόδοση είναι διαφορετικά.

Να θυμάστε ότι όταν χρειάζεστε μια συνάρτηση για την αρχική κατάσταση, μεταβιβάζετε πάντα τη συνάρτηση ή καλείτε τη συνάρτηση μέσα σε άλλη συνάρτηση. Ποτέ μην καλείτε απευθείας τη λειτουργία.

✅ const [items, setItems] = useState(getItems);
✅ const [items, setItems] = useState(() => getItems());
❌ const [items, setItems] = useState(getItems());

Πόσες χρήσεις State hooks μπορώ να έχω

Μπορείτε να έχετε όσα άγκιστρα useState μέσα σε ένα εξάρτημα χρειάζεται.

Δείτε το CodeSandbox

Πολλαπλές χρήσεις State hooks

Το παρακάτω στοιχείο έχει τρεις διαφορετικές καταστάσεις – όνομα χρήστη, κωδικός πρόσβασης, keepMeSignedIn.

Δοκιμάστε να ενημερώσετε τις τιμές του ονόματος χρήστη, keepMeSignedIn. Οι ενημερωμένες καταστάσεις καταγράφονται στην κονσόλα όταν κάνετε κλικ στο κουμπί σύνδεσης.

Highlights

  • Το useState παρέχει έναν μηχανισμό για την ενεργοποίηση μιας εκ νέου απόδοσης και τη διατήρηση της κατάστασης μεταξύ των αναπαραγωγών.
  • Χρησιμοποιήστε τη λειτουργία ενημέρωσης όταν χρειάζεται:
    • Υπολογίστε την επόμενη κατάσταση με βάση την προηγούμενη κατάσταση.
    • Εκτελέστε πολλαπλές ενημερώσεις στην κατάσταση πριν από την επόμενη απόδοση.
  • Εάν η αρχική κατάσταση λαμβάνεται από μια συνάρτηση - χρησιμοποιήστε τη σύνταξη της συνάρτησης αρχικοποιητή.
  • Μπορεί να υπάρχουν πολλαπλές αγκίστριες κατάστασης χρήσης μέσα σε ένα στοιχείο.

Σας άρεσε αυτή η ανάρτηση; Μοιραστείτε το με άλλους.
Γράφτηκε αρχικά για το προσωπικό μου ιστολόγιο - https://gauravsen.com/use-state-hook

Σφραγίδα ώρας:

Περισσότερα από Codementor React Fact