Hook React - usando useState vs solo variabili


12

React Hooks ci offre l'opzione useState e vedo sempre confronti di Hooks vs Class-State. Ma che dire di Hooks e di alcune variabili regolari?

Per esempio,

function Foo() {
    let a = 0;
    a = 1;
    return <div>{a}</div>;
}

Non ho usato Hooks e mi darà gli stessi risultati di:

function Foo() {
    const [a, setA] = useState(0);
    if (a != 1) setA(1); // to avoid infinite-loop
    return <div>{a}</div>;
}

Quindi qual è la differenza? L'uso di Hooks è ancora più complesso per quel caso ... Allora perché iniziare a usarlo?


Stai confrontando 2 cose diverse però. La seconda funzione con hook ha la capacità di aggiornare i dati. Il primo non sta davvero facendo nulla. Avresti potuto inizializzarlo con let a = 1; return <div>{a}</div>e otterrai lo stesso risultato.
Yathi,

Risposte:


13

Il motivo è se si useStaterende nuovamente la vista. Le variabili da sole cambiano solo i bit in memoria e lo stato della tua app può non essere sincronizzato con la vista.

Confronta questi esempi:

function Foo() {
    const [a, setA] = useState(0);
    return <div onClick={() => setA(a + 1)}>{a}</div>;
}

function Foo() {
    let a = 0;
    return <div onClick={() => a + 1}>{a}</div>;
}

In entrambi i casi le amodifiche al clic, ma solo quando si utilizza useStatela vista mostra correttamente ail valore corrente.


Grazie! Quindi, se non ho bisogno di renderizzare la vista - solo un modo per organizzare i miei dati (oggetti di scena) in un array - posso usare 'let'? Funziona per me, voglio solo sapere che va bene e accettabile.
Moshe Nagar,

@MosheNagar se si ricavano i propri dati dagli oggetti di scena, si consiglia di utilizzare le variabili locali invece di mantenere i dati nello stato perché il componente eseguirà nuovamente il rendering sulla modifica dell'elica, quindi la vista sarà sincronizzata con i dati. Metterli in stato provocherebbe solo un rendering non necessario - prima sul cambio di prop, poi sul cambio di stato.
Marzelin,

Un altro modo di guardare a questa risposta è pensare che nel secondo caso, la variabile asarà spazzatura raccolta dopo che ha terminato l'esecuzione, mentre nel primo, poiché sfrutta useState, conserverà il valore dia
João Marcos Gris

Poteva ancora usarlo useRefse non voleva ridare il rendering alla vista. Resta da chiedersi se dovrebbe usare variabili locali o riferimenti a React. Ad esempio, se si dispone di un timeout che è necessario cancellare o di una richiesta http in corso utilizzando axios, si memorizza il timeout o la sorgente axios in una variabile o in un riferimento React?
Tom,

3
@ Tom La regola generale è utilizzare VAR locali per lo stato derivato. Per qualcos'altro utilizzare useRef(se non si desidera il rendering) o useState(se si desidera il rendering). Nel caso dei timer, poiché sono effetti collaterali, dovrebbero essere avviati useEffect. Se si desidera timerIdsolo a fini di pulizia, è possibile mantenerlo nella variabile locale del gestore . Se si desidera essere in grado di cancellare il timer da un'altra posizione nel componente, è necessario utilizzare useRef. La memorizzazione timerIdnella variabile locale di un componente sarebbe un errore poiché i parametri locali vengono "ripristinati" su ogni rendering.
Marzelin,

1

L'aggiornamento dello stato renderà nuovamente il componente di nuovo rendering, ma i valori locali non lo sono.

Nel tuo caso, hai reso quel valore nel tuo componente. Ciò significa che, quando il valore viene modificato, il componente deve essere ridistribuito per mostrare il valore aggiornato.

Quindi sarà meglio usare useStaterispetto al normale valore locale.

function Foo() {
    let a = 0;
    a = 1; // there will be no re-render.
    return <div>{a}</div>;
}

function Foo() {
    const [a, setA] = useState(0);
    if (a != 1) setA(1); // re-render required
    return <div>{a}</div>;
}

0

Il tuo primo esempio funziona solo perché i dati essenzialmente non cambiano mai. Il punto di accesso dell'utilizzo setStateè il rendering dell'intero componente quando lo stato si blocca. Quindi, se il tuo esempio richiede una sorta di cambio o gestione dello stato, ti renderai presto conto che i valori di cambiamento saranno necessari e per aggiornare la vista con il valore della variabile, avrai bisogno dello stato e del nuovo rendering.


0
function Foo() {
    const [a, setA] = useState(0);
    if (a != 1) setA(1); // to avoid infinite-loop
    return <div>{a}</div>;
}

è equivalente a

class Foo extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            a: 0
        };
    }
    // ...
}

Ciò che useStateritorna sono due cose:

  1. nuova variabile di stato
  2. setter per quella variabile

se chiami setA(1), chiameresti this.setState({ a: 1 })e attiveresti un nuovo rendering.


0

Le variabili locali verranno resettate ad ogni rendering dopo la mutazione mentre lo stato aggiornerà:

function App() {
  let a = 0; // reset to 0 on render/re-render
  const [b, setB] = useState(0);

  return (
    <div className="App">
      <div>
        {a}
        <button onClick={() => a++}>local variable a++</button>
      </div>
      <div>
        {b}
        <button onClick={() => setB(prevB => prevB + 1)}>
          state variable b++
        </button>
      </div>
    </div>
  );
}

Modifica serene-galileo-ml3f0

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.