Qu'est-ce que useState () dans React?

134

J'apprends actuellement le concept de hooks dans React et j'essaie de comprendre l'exemple ci-dessous.

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'exemple ci-dessus incrémente le compteur sur le paramètre de fonction de gestionnaire lui-même. Que faire si je veux modifier la valeur de comptage dans la fonction de gestionnaire d'événements

Considérez l'exemple ci-dessous

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>
Hemadri Dasari
la source
Vous pouvez également consulter le code source pour comprendre comment useStateest implémenté. Voici la définition à partir de la version 16.9 .
chemturion

Réponses:

148

Les hooks React sont une nouvelle façon (encore en cours de développement) d'accéder aux fonctionnalités de base de react comme statesans avoir à utiliser de classes, dans votre exemple si vous voulez incrémenter un compteur directement dans la fonction handler sans le spécifier directement dans le onClickprop, vous pourrait faire quelque chose comme:

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

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

et onClick:

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

Expliquons rapidement ce qui se passe dans cette ligne:

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

useState(0)retourne un tuple où le premier paramètre countest l'état actuel du compteur et setCounterest la méthode qui nous permettra de mettre à jour l'état du compteur. Nous pouvons utiliser la setCounterméthode pour mettre à jour l'état de countn'importe où - Dans ce cas, nous l'utilisons à l'intérieur de la setCountfonction où nous pouvons faire plus de choses; l'idée avec les hooks est que nous sommes en mesure de garder notre code plus fonctionnel et d'éviter les composants basés sur les classes s'ils ne sont pas souhaités / nécessaires.

J'ai écrit un article sur les crochets avec de multiples exemples (y compris les compteurs), comme ce codepen , je utilisais useState, useEffect, useContextet crochets personnalisés . Je pourrais entrer dans plus de détails sur le fonctionnement des hooks sur cette réponse, mais la documentation fait un très bon travail en expliquant en détail le hook d'état et d'autres hooks, j'espère que cela vous aidera.

mise à jour: les Hooks ne sont plus une proposition , depuis la version 16.8 ils sont maintenant disponibles pour être utilisés, il y a une section dans le site de React qui répond à une partie de la FAQ .

Enmanuel Duran
la source
2
Bonne analogie sauf que JavaScript n'a techniquement pas de type de données tuple
goonerify
Eh bien, l'affectation déstructurée est utilisée comme tuple stackoverflow.com/a/4513061/6335029
NaveenDA
Les hooks sont-ils asynchrones? Lors de l'utilisation setSomething, si j'essaye ensuite de l'utiliser somethingdirectement après, il semble avoir toujours l'ancienne valeur ...
Byron Coetsee
51

useStateest l'un des hooks de réaction intégrés disponibles dans la 0.16.7version.

useStatene doit être utilisé qu'à l'intérieur des composants fonctionnels. useStatec'est le moyen si nous avons besoin d'un état interne et que nous n'avons pas besoin d'implémenter une logique plus complexe telle que des méthodes de cycle de vie.

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

Renvoie une valeur avec état et une fonction pour la mettre à jour.

Lors du rendu initial, l'état renvoyé (state) est le même que la valeur transmise comme premier argument (initialState).

La fonction setState est utilisée pour mettre à jour l'état. Il accepte une nouvelle valeur d'état et met en file d'attente un nouveau rendu du composant.

Veuillez noter que le useStaterappel de hook pour la mise à jour de l'état se comporte différemment des composants this.setState. Pour vous montrer la différence, j'ai préparé deux exemples.

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/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>

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

Un nouvel objet est créé lorsque le setUserInforappel est utilisé. Notez que nous avons perdu la lastNamevaleur clé. Pour corriger cela, nous pourrions passer la fonction à l'intérieur useState.

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

Voir exemple:

// 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/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>

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

Contrairement à la méthode setState trouvée dans les composants de classe, useState ne fusionne pas automatiquement les objets de mise à jour. Vous pouvez reproduire ce comportement en combinant le formulaire de mise à jour de fonction avec la syntaxe de propagation d'objet:

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

Pour en savoir plus, useStateconsultez la documentation officielle .

Loelsonk
la source
2
Merci d'avoir ajouté une fonction en tant que paramètre dans l'exemple.
Juni Brosas le
15

La syntaxe de useStatehook est simple.

const [value, setValue] = useState(defaultValue)

Si vous n'êtes pas familier avec cette syntaxe, allez ici .

Je vous recommande de lire la documentation . Il y a d'excellentes explications avec une quantité décente d'exemples.

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

Jan Ciołek
la source
Cela devrait être la réponse acceptée. Concis et clair, avec de bonnes références externes.
varun
8

useStateest l'un des hooks disponibles dans React v16.8.0. Il vous permet essentiellement de transformer vos composants fonctionnels / sans état en un seul qui peut avoir son propre état.

Au niveau très basique, il est utilisé de cette façon:

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

Cela vous permet ensuite d'appeler en setLoadingpassant une valeur booléenne. C'est une manière sympa d'avoir un composant fonctionnel "avec état".

codejockie
la source
7

useState()est un hook React. Les hooks permettent d'utiliser l'état et la mutabilité à l'intérieur des composants de fonction.

Bien que vous ne puissiez pas utiliser de hooks à l'intérieur de classes, vous pouvez encapsuler votre composant de classe avec une fonction et utiliser des hooks. C'est un excellent outil pour migrer des composants d'une classe à une fonction. Voici un exemple complet:

Pour cet exemple, j'utiliserai un composant compteur. Ça y est:

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>

Il s'agit d'un composant de classe simple avec un état de comptage et la mise à jour de l'état est effectuée par des méthodes. C'est un modèle très courant dans les composants de classe. La première chose est de l'envelopper avec un composant de fonction avec juste le même nom, qui délègue toutes ses propriétés au composant encapsulé. Vous devez également rendre le composant encapsulé dans le retour de fonction. C'est ici:

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>

C'est exactement le même composant, avec le même comportement, le même nom et les mêmes propriétés. Élevons maintenant l'état de comptage au composant de fonction. Voici comment ça se passe:

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>

Notez que la méthode incest toujours là, elle ne blessera personne, en fait c'est du code mort. C'est l'idée, continuez simplement à soulever l'état. Une fois que vous avez terminé, vous pouvez supprimer le composant de 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>

Bien que cela permette d'utiliser des crochets dans des composants de classe, je ne vous recommanderais pas de le faire, sauf si vous migrez comme je l'ai fait dans cet exemple. Le mélange des composants de la fonction et de la classe rendra la gestion de l'état un désordre. J'espère que ça aide

Meilleures salutations

geckos
la source
7

useState () est un exemple de hook React intégré qui vous permet d'utiliser des états dans vos composants fonctionnels. Cela n'était pas possible avant React 16.7.

La fonction useState est un hook intégré qui peut être importé depuis le package react. Il vous permet d'ajouter un état à vos composants fonctionnels. En utilisant le hook useState dans un composant de fonction, vous pouvez créer un élément d'état sans passer aux composants de classe.

Muhammad Shaheem
la source
5

Les hooks sont une nouvelle fonctionnalité dans React v16.7.0-alpha useStatele "Hook". useState()définir la valeur par défaut de la variable any et gérer le composant de fonction (fonctions PureComponent). ex : const [count, setCount] = useState(0);définir la valeur par défaut de count 0. et u peut utiliser setCountto incrementou decrementla valeur. onClick={() => setCount(count + 1)}incrémenter la valeur de comptage. DOC

Asif vora
la source
5

Merci Loelsonk, je l'ai fait

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

Yanov
la source
2

useState est un hook qui vous permet d'ajouter un état à un composant fonctionnel. Il accepte un argument qui est la valeur initiale de la propriété d'état et renvoie la valeur actuelle de la propriété d'état et une méthode qui est capable de mettre à jour cette propriété d'état.
Voici un exemple simple:
import React, {useState} from react
function HookCounter {
const [count, stateCount]= useState(0)
return(
<div>
<button onClick{( ) => setCount(count+1)}> count{count} </button>
</div>
)
}

useState accepte la valeur initiale de la variable d'état qui est zéro dans ce cas et renvoie une paire de valeurs. La valeur actuelle de l'état a été appelée count et une méthode qui peut mettre à jour la variable d'état a été appelée setCount.

Abhishek Kumar
la source