Cos'è useState () in React?


134

Attualmente sto imparando il concetto di hook in React e sto cercando di capire l'esempio seguente.

import { useState } from 'react';

function Example() {
    // Declare a new state variable, which we'll call "count"
    const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

L'esempio precedente incrementa il contatore sul parametro della funzione gestore stesso. E se volessi modificare il valore di conteggio all'interno della funzione del gestore eventi

Considera l'esempio seguente

setCount = () => {
  //how can I modify count value here. Not sure if I can use setState to modify its value
  //also I want to modify other state values as well here. How can I do that
}

<button onClick={() => setCount()}>
  Click me
</button>

Puoi anche guardare nel codice sorgente per capire come useStateviene implementato. Ecco la definizione a partire dalla versione 16.9 .
Chemturion

Risposte:


148

Gli hook di React sono un nuovo modo (ancora in fase di sviluppo) per accedere alle funzionalità principali di React come statesenza dover usare le classi, nel tuo esempio se vuoi incrementare un contatore direttamente nella funzione handler senza specificarlo direttamente nel onClickprop, tu potrebbe fare qualcosa come:

...
const [count, setCounter] = useState(0);
const [moreStuff, setMoreStuff] = useState(...);
...

const setCount = () => {
    setCounter(count + 1);
    setMoreStuff(...);
    ...
};

e suClic:

<button onClick={setCount}>
    Click me
</button>

Spieghiamo rapidamente cosa sta succedendo in questa riga:

const [count, setCounter] = useState(0);

useState(0)restituisce una tupla dove il primo parametro countè lo stato corrente del contatore ed setCounterè il metodo che ci permetterà di aggiornare lo stato del contatore. Possiamo usare il setCountermetodo per aggiornare lo stato di countqualsiasi luogo - In questo caso lo stiamo usando all'interno della setCountfunzione dove possiamo fare più cose; l'idea con gli hook è che siamo in grado di mantenere il nostro codice più funzionale ed evitare componenti basati su classi se non desiderati / necessari.

Ho scritto un articolo completo su ganci con molteplici esempi (tra cui i contatori) come questo codepen , ho fatto uso di useState, useEffect, useContexte ganci personalizzati . Potrei entrare in maggiori dettagli su come funzionano gli hook su questa risposta, ma la documentazione fa un ottimo lavoro spiegando in dettaglio l' hook di stato e altri hook, spero che aiuti.

aggiornamento: Gli hook non sono più una proposta , poiché la versione 16.8 è ora disponibile per essere utilizzata, c'è una sezione nel sito di React che risponde ad alcune delle FAQ .


2
Buona analogia, tranne per il fatto che JavaScript non ha tecnicamente un tipo di dati tupla
goonerify il

Ebbene, l'assegnazione destrutturato viene utilizzato come tuple stackoverflow.com/a/4513061/6335029
NaveenDA

Gli hook sono asincroni? Quando lo uso setSomething, se provo a usarlo somethingsubito dopo, sembra che abbia ancora il vecchio valore ...
Byron Coetsee

51

useStateè uno degli hook di reazione incorporati disponibili nella 0.16.7versione.

useStatedeve essere utilizzato solo all'interno di componenti funzionali. useStateè il modo se abbiamo bisogno di uno stato interno e non è necessario implementare una logica più complessa come i metodi del ciclo di vita.

const [state, setState] = useState(initialState);

Restituisce un valore stateful e una funzione per aggiornarlo.

Durante il rendering iniziale, lo stato (state) restituito è uguale al valore passato come primo argomento (initialState).

La funzione setState viene utilizzata per aggiornare lo stato. Accetta un nuovo valore di stato e accoda un nuovo rendering del componente.

Si noti che il useStatecallback hook per l'aggiornamento dello stato si comporta in modo diverso rispetto ai componenti this.setState. Per mostrarti la differenza ho preparato due esempi.

class UserInfoClass extends React.Component {
  state = { firstName: 'John', lastName: 'Doe' };
  
  render() {
    return <div>
      <p>userInfo: {JSON.stringify(this.state)}</p>
      <button onClick={() => this.setState({ 
        firstName: 'Jason'
      })}>Update name to Jason</button>
    </div>;
  }
}

// Please note that new object is created when setUserInfo callback is used
function UserInfoFunction() {
  const [userInfo, setUserInfo] = React.useState({ 
    firstName: 'John', lastName: 'Doe',
  });

  return (
    <div>
      <p>userInfo: {JSON.stringify(userInfo)}</p>
      <button onClick={() => setUserInfo({ firstName: 'Jason' })}>Update name to Jason</button>
    </div>
  );
}

ReactDOM.render(
  <div>
    <UserInfoClass />
    <UserInfoFunction />
  </div>
, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>

Quando setUserInfoviene utilizzato il callback, viene creato un nuovo oggetto . Notare che abbiamo perso il lastNamevalore della chiave. Per risolverlo potremmo passare la funzione all'interno useState.

setUserInfo(prevState => ({ ...prevState, firstName: 'Jason' })

Vedi esempio:

// Please note that new object is created when setUserInfo callback is used
function UserInfoFunction() {
  const [userInfo, setUserInfo] = React.useState({ 
    firstName: 'John', lastName: 'Doe',
  });

  return (
    <div>
      <p>userInfo: {JSON.stringify(userInfo)}</p>
      <button onClick={() => setUserInfo(prevState => ({
        ...prevState, firstName: 'Jason' }))}>
        Update name to Jason
      </button>
    </div>
  );
}

ReactDOM.render(
    <UserInfoFunction />
, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>

A differenza del metodo setState trovato nei componenti di classe, useState non unisce automaticamente gli oggetti di aggiornamento. È possibile replicare questo comportamento combinando il modulo di aggiornamento della funzione con la sintassi di diffusione degli oggetti:

setState(prevState => {
  // Object.assign would also work
  return {...prevState, ...updatedValues};
});

Per ulteriori informazioni, useStatevedere la documentazione ufficiale .


2
Grazie per aver aggiunto una funzione come parametro nell'esempio.
Juni Brosas,

15

La sintassi di useStatehook è semplice.

const [value, setValue] = useState(defaultValue)

Se non hai familiarità con questa sintassi, vai qui .

Ti consiglierei di leggere la documentazione . Ci sono ottime spiegazioni con una discreta quantità di esempi.

import { useState } from 'react';

function Example() {
    // Declare a new state variable, which we'll call "count"
    const [count, setCount] = useState(0);
  
  // its up to you how you do it
  const buttonClickHandler = e => {
   // increment
   // setCount(count + 1)
   
   // decrement
   // setCount(count -1)
   
   // anything
   // setCount(0)
  }
  

  return (
       <div>
          <p>You clicked {count} times</p>
         <button onClick={buttonClickHandler}>
             Click me
         </button>
      </div>
   );
 }


Questa dovrebbe essere la risposta accettata. Conciso e chiaro, con buoni riferimenti esterni.
Varun

8

useStateè uno degli hook disponibili in React v16.8.0. Fondamentalmente ti consente di trasformare i tuoi componenti altrimenti non stateful / funzionali in uno che può avere il proprio stato.

A livello di base, viene utilizzato in questo modo:

const [isLoading, setLoading] = useState(true);

Questo ti consente quindi di chiamare setLoadingpassando un valore booleano. È un modo fantastico di avere componenti funzionali "stateful".


7

useState()è un gancio React. Gli hook rendono possibile l'uso di stato e mutabilità all'interno di componenti funzionali.

Sebbene non sia possibile utilizzare gli hook all'interno delle classi, è possibile avvolgere il componente della classe con uno di funzione e utilizzare gli hook da esso. Questo è un ottimo strumento per migrare i componenti dalla classe alla forma della funzione. Ecco un esempio completo:

Per questo esempio userò un componente contatore. Questo è:

class Hello extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: props.count };
  }
  
  inc() {
    this.setState(prev => ({count: prev.count+1}));
  }
  
  render() {
    return <button onClick={() => this.inc()}>{this.state.count}</button>
  }
}

ReactDOM.render(<Hello count={0}/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='root'></div>

È un semplice componente di classe con uno stato di conteggio e l'aggiornamento dello stato viene eseguito mediante metodi. Questo è un modello molto comune nei componenti di classe. La prima cosa è avvolgerlo con un componente funzione con lo stesso nome, che deleghi tutte le sue proprietà al componente avvolto. Inoltre è necessario eseguire il rendering del componente avvolto nella funzione return. Ecco qui:

function Hello(props) {
  class Hello extends React.Component {
    constructor(props) {
      super(props);
      this.state = { count: props.count };
    }

    inc() {
      this.setState(prev => ({count: prev.count+1}));
    }

    render() {
      return <button onClick={() => this.inc()}>{this.state.count}</button>
    }
  }
  return <Hello {...props}/>
}

ReactDOM.render(<Hello count={0}/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='root'></div>

Questo è esattamente lo stesso componente, con lo stesso comportamento, lo stesso nome e le stesse proprietà. Ora eleviamo lo stato di conteggio al componente funzione. Le cose stanno così:

function Hello(props) {
  const [count, setCount] = React.useState(0);
  class Hello extends React.Component {
    constructor(props) {
      super(props);
      this.state = { count: props.count };
    }

    inc() {
      this.setState(prev => ({count: prev.count+1}));
    }

    render() {
      return <button onClick={() => setCount(count+1)}>{count}</button>
    }
  }
  return <Hello {...props}/>
}

ReactDOM.render(<Hello count={0}/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js" integrity="sha256-3vo65ZXn5pfsCfGM5H55X+SmwJHBlyNHPwRmWAPgJnM=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js" integrity="sha256-qVsF1ftL3vUq8RFOLwPnKimXOLo72xguDliIxeffHRc=" crossorigin="anonymous"></script>
<div id='root'></div>

Nota che il metodo incè ancora lì, non farà male a nessuno, infatti è codice morto. Questa è l'idea, continua a sollevare lo stato. Una volta terminato, puoi rimuovere il componente di classe:

function Hello(props) {
  const [count, setCount] = React.useState(0);

  return <button onClick={() => setCount(count+1)}>{count}</button>;
}

ReactDOM.render(<Hello count={0}/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js" integrity="sha256-3vo65ZXn5pfsCfGM5H55X+SmwJHBlyNHPwRmWAPgJnM=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js" integrity="sha256-qVsF1ftL3vUq8RFOLwPnKimXOLo72xguDliIxeffHRc=" crossorigin="anonymous"></script>

<div id='root'></div>

Sebbene ciò renda possibile l'uso di hook all'interno dei componenti della classe, non ti consiglierei di farlo tranne se stai migrando come ho fatto in questo esempio. La combinazione di funzioni e componenti di classe renderà la gestione dello stato un pasticcio. Spero che aiuti

I migliori saluti


7

useState () è un esempio di hook React integrato che ti consente di utilizzare gli stati nei tuoi componenti funzionali. Questo non era possibile prima di React 16.7.

La funzione useState è un hook integrato che può essere importato dal pacchetto react. Ti consente di aggiungere stato ai tuoi componenti funzionali. Utilizzando l'hook useState all'interno di un componente funzione, è possibile creare un pezzo di stato senza passare ai componenti di classe.


5

I ganci sono una nuova funzionalità in React v16.7.0-alpha useStateè il "gancio". useState()imposta il valore predefinito di qualsiasi variabile e gestisci il componente funzione (funzioni PureComponent). ex : const [count, setCount] = useState(0);impostare il valore predefinito di conteggio 0. e u possibile utilizzare setCountper incremento decrementil valore. onClick={() => setCount(count + 1)}incrementare il valore di conteggio. DOC


5

Grazie Loelsonk, l'ho fatto

const [dataAction, setDataAction] = useState({name: '', description: ''});

    const _handleChangeName = (data) => {
        if(data.name)
            setDataAction( prevState  => ({ ...prevState,   name : data.name }));
        if(data.description)
            setDataAction( prevState  => ({ ...prevState,   description : data.description }));
    };
    
    ....return (
    
          <input onChange={(event) => _handleChangeName({name: event.target.value})}/>
          <input onChange={(event) => _handleChangeName({description: event.target.value})}/>
    )


2

useState è un hook che ti consente di aggiungere stato a un componente funzionale. Accetta un argomento che è il valore iniziale della proprietà state e restituisce il valore corrente della proprietà state e un metodo che è in grado di aggiornare quella proprietà state.
Di seguito è riportato un semplice esempio:
import React, {useState} from react
function HookCounter {
const [count, stateCount]= useState(0)
return(
<div>
<button onClick{( ) => setCount(count+1)}> count{count} </button>
</div>
)
}

useState accetta il valore iniziale della variabile di stato che in questo caso è zero e restituisce una coppia di valori. Il valore corrente dello stato è stato chiamato count e un metodo che può aggiornare la variabile di stato è stato chiamato setCount.

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.