¿Qué es useState () en React?

134

Actualmente estoy aprendiendo el concepto de ganchos en React y tratando de entender el siguiente ejemplo.

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

El ejemplo anterior incrementa el contador en el parámetro de la función del controlador. ¿Qué sucede si quiero modificar el valor de conteo dentro de la función del controlador de eventos?

Considere el siguiente ejemplo

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
fuente
También puede consultar el código fuente para comprender cómo useStatese implementa. Aquí está la definición a partir de la versión 16.9 .
chemturion

Respuestas:

148

Los ganchos de reacción son una nueva forma (aún en desarrollo) de acceder a las características centrales de la reacción, como statesin tener que usar clases, en su ejemplo, si desea incrementar un contador directamente en la función del controlador sin especificarlo directamente en el onClickaccesorio, usted podría hacer algo como:

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

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

y onClick:

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

Expliquemos rápidamente lo que está sucediendo en esta línea:

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

useState(0)devuelve una tupla donde el primer parámetro countes el estado actual del contador y setCounteres el método que nos permitirá actualizar el estado del contador. Podemos usar el setCountermétodo para actualizar el estado de countcualquier lugar: en este caso, lo estamos usando dentro de la setCountfunción donde podemos hacer más cosas; La idea con los ganchos es que podemos mantener nuestro código más funcional y evitar componentes basados ​​en clases si no se desea / necesita.

Escribí un artículo completo acerca de ganchos con múltiples ejemplos (incluyendo contadores) como esta codepen , hice uso de useState, useEffect, useContext, y ganchos personalizados . Podría entrar en más detalles sobre cómo funcionan los ganchos en esta respuesta, pero la documentación hace un muy buen trabajo explicando el gancho de estado y otros ganchos en detalle, espero que ayude.

actualización: los ganchos ya no son una propuesta , ya que la versión 16.8 ahora están disponibles para su uso, hay una sección en el sitio de React que responde a algunas de las preguntas frecuentes .

Enmanuel Duran
fuente
2
Buena analogía, excepto que JavaScript técnicamente no tiene un tipo de datos de tupla
goonerify
Bueno, la asignación desestructurada se usa como tuple stackoverflow.com/a/4513061/6335029
NaveenDA
¿Los ganchos son asíncronos? Cuando lo uso setSomething, si luego trato de usarlo somethingdirectamente después, parece que todavía tiene el valor anterior ...
Byron Coetsee
51

useStatees uno de los ganchos de reacción integrados disponibles en la 0.16.7versión.

useStatedebe usarse solo dentro de componentes funcionales. useStatees la forma si necesitamos un estado interno y no necesitamos implementar una lógica más compleja como los métodos del ciclo de vida.

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

Devuelve un valor con estado y una función para actualizarlo.

Durante el renderizado inicial, el estado (estado) devuelto es el mismo que el valor pasado como primer argumento (initialState).

La función setState se usa para actualizar el estado. Acepta un nuevo valor de estado y pone en cola una nueva representación del componente.

Tenga en cuenta que la useStatedevolución de llamada de enlace para actualizar el estado se comporta de manera diferente que los componentes this.setState. Para mostrarle la diferencia, preparé dos ejemplos.

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>

Se crea un nuevo objeto cuando setUserInfose utiliza la devolución de llamada. Observe que perdimos el lastNamevalor clave. Para arreglar eso podríamos pasar función dentro useState.

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

Ver ejemplo:

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

A diferencia del método setState que se encuentra en los componentes de la clase, useState no combina automáticamente los objetos de actualización. Puede replicar este comportamiento combinando el formulario de actualización de funciones con la sintaxis de propagación de objetos:

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

Para más información sobre useStatever la documentación oficial .

loelsonk
fuente
2
Gracias por agregar una función como parámetro en el ejemplo.
Juni Brosas
15

La sintaxis de useStatehook es sencilla.

const [value, setValue] = useState(defaultValue)

Si no está familiarizado con esta sintaxis, vaya aquí .

Le recomendaría que lea la documentación . Hay excelentes explicaciones con una cantidad decente de ejemplos.

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
fuente
Esta debería ser la respuesta aceptada. Conciso y claro, con buenas referencias externas.
Varun
8

useStatees uno de los ganchos disponibles en React v16.8.0. Básicamente, le permite convertir sus componentes que no tienen estado / funcionales a uno que pueda tener su propio estado.

En el nivel más básico, se usa de esta manera:

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

Esto le permite llamar setLoadingpasando un valor booleano. Es una forma genial de tener un componente funcional "con estado".

codejockie
fuente
7

useState()Es un gancho de reacción. Los ganchos permiten utilizar el estado y la mutabilidad dentro de los componentes de la función.

Si bien no puede usar ganchos dentro de las clases, puede ajustar su componente de clase con una función y usar ganchos de él. Esta es una gran herramienta para migrar componentes de la clase a la forma funcional. Aquí hay un ejemplo completo:

Para este ejemplo, usaré un componente de contador. Eso es todo:

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>

Es un componente de clase simple con un estado de conteo, y la actualización del estado se realiza por métodos. Este es un patrón muy común en los componentes de clase. Lo primero es envolverlo con un componente de función con el mismo nombre, que delegue todas sus propiedades al componente envuelto. También debe representar el componente envuelto en la función return. Aquí está:

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>

Este es exactamente el mismo componente, con el mismo comportamiento, el mismo nombre y las mismas propiedades. Ahora levantemos el estado de conteo al componente de función. Así es como va:

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>

Tenga en cuenta que el método inctodavía está allí, no dañará a nadie, de hecho, es un código muerto. Esta es la idea, solo sigue levantando el estado. Una vez que haya terminado, puede eliminar el componente de clase:

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>

Si bien esto hace posible usar ganchos dentro de los componentes de la clase, no recomendaría que lo haga, excepto si migra como lo hice en este ejemplo. La combinación de funciones y componentes de clase hará que la gestión del estado sea un desastre. espero que esto ayude

Atentamente

gecos
fuente
7

useState () es un ejemplo de enlace de React incorporado que le permite usar estados en sus componentes funcionales. Esto no fue posible antes de React 16.7.

La función useState es un enlace integrado que se puede importar desde el paquete react. Le permite agregar estado a sus componentes funcionales. Usando el gancho useState dentro de un componente de función, puede crear una pieza de estado sin cambiar a componentes de clase.

Muhammad Shaheem
fuente
5

Los ganchos son una característica nueva en React v16.7.0-alpha useStateel "gancho". useState()establezca el valor predeterminado de cualquier variable y administre en el componente de función (funciones PureComponent). ex : const [count, setCount] = useState(0);establece el valor predeterminado del recuento 0. y puedes usar setCountto incremento decrementel valor. onClick={() => setCount(count + 1)}incremente el valor de conteo. DOC

Asif vora
fuente
5

Gracias loelsonk, lo hice

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

Анов Алексей
fuente
2

useState es un enlace que le permite agregar estado a un componente funcional. Acepta un argumento que es el valor inicial de la propiedad del estado y devuelve el valor actual de la propiedad del estado y un método que es capaz de actualizar esa propiedad del estado.
El siguiente es un ejemplo 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 acepta el valor inicial de la variable de estado que es cero en este caso y devuelve un par de valores. El valor actual del estado se ha denominado recuento y un método que puede actualizar la variable de estado se ha denominado como setCount.

Abhishek Kumar
fuente