Cuándo utilizar setState funcional

Resuelto physicsboy asked hace 6 años • 3 respuestas

He estado aprendiendo React durante los últimos días, viendo algunos tutoriales y explicaciones sobre las diferentes formas en que puedes escribir diferentes elementos. Sin embargo, hay algo sobre lo que he tenido más curiosidad: la setStatefunción para actualizar/anular las statepropiedades de un componente.

Por ejemplo, imagina que tengo una clase con lo siguiente:

class Photos extends React.Component {
    constructor() {
        super()
        state = {
            pictures: []
        }
    }

   componentDidMount() {
      // This is where the fetch and setState will occur (see below)
   }

    render() {
       return {
          <div className="container">
             {this.state.pictures}
          </div>
       }
    }
}

En este ejemplo, obtengo imágenes de una API.

Dado que realicé la búsqueda, el mapeo y el retorno para esta función, luego actualizaré la pictures: []matriz de estado con los resultados obtenidos en la llamada API.

Mi pregunta surge de los diferentes métodos que he visto sobre cómo actualizar/anular la propiedad de estado de las imágenes.

Lo he visto escrito de 2 formas diferentes:

1) Este parece ser un método muy simple y fácil de leer.

this.setState({pictures: pics})

2) Esto es más complejo pero lo veo descrito como un método más seguro.

this.setState(prevState => ({
   pictures: prevState.pictures.concat(pics)
}))

¿Alguien podría explicar las ventajas de utilizar cualquiera de los dos? Quiero ser coherente con el código en el futuro, al tratar con accesorios y estados, etc., por lo que, por supuesto, sería preferible el método más versátil.

physicsboy avatar Jan 11 '18 21:01 physicsboy
Aceptado

Lo primero es lo primero, en su caso las dos sintaxis son completamente diferentes, lo que podría estar buscando es la diferencia entre

this.setState({pictures: this.state.picture.concat(pics)})

y

this.setState(prevState => ({
   pictures: prevState.pictures.concat(pics)
}))

Para comprender por qué se prefiere el segundo método, debe comprender qué hace React setState()internamente.

React primero fusionará el objeto al que pasó setState()en el estado actual. Entonces comenzará eso de la reconciliación. Debido a la llamada, setState()es posible que no actualice inmediatamente su estado.

React puede agrupar varias setState()llamadas en una sola actualización para un mejor rendimiento.

Considere el caso simple, para entender esto, en su función puede llamar setState()más de una vez como:

myFunction = () => {

   ...
   this.setState({pictures: this.state.picture.concat(pics1)})
   this.setState({pictures: this.state.picture.concat(pics1)})
   this.setState({pictures: this.state.picture.concat(pics1)})

   ...
}

lo cual no es un caso de uso válido en una aplicación simple, pero a medida que la aplicación se vuelve compleja, setState()es posible que se realicen múltiples llamadas desde múltiples lugares, haciendo lo mismo.

Entonces, ahora, para realizar una actualización eficiente, React realiza el procesamiento por lotes extrayendo todos los objetos pasados ​​a cada setState()llamada, los fusiona para formar un solo objeto y luego usa ese único objeto para hacer setState(). Según la setState()documentación:

Esta forma de setState()también es asincrónica y se pueden agrupar varias llamadas durante el mismo ciclo. Por ejemplo, si intenta incrementar la cantidad de un artículo más de una vez en el mismo ciclo, obtendrá el equivalente a:

Object.assign(
  previousState,
  {quantity: state.quantity + 1},
  {quantity: state.quantity + 1},
  ...
)

Las llamadas posteriores anularán los valores de llamadas anteriores en el mismo ciclo, por lo que la cantidad solo se incrementará una vez. Si el siguiente estado depende del estado actual, recomendamos utilizar el formulario de función de actualización en su lugar:

this.setState((state) => {
  return {quantity: state.quantity + 1};
});

Para obtener más detalles, consulte:

  • Guía de estado y ciclo de vida
  • En profundidad: ¿Cuándo y por qué se setState()agrupan las llamadas?
  • En profundidad: ¿Por qué no se this.stateactualiza inmediatamente?

setState()- Otras API - React.Component – ​​React .

Entonces, si alguno de los objetos contiene la misma clave, se almacena el valor de la clave del último objeto con la misma clave. Y por lo tanto la actualización sólo ocurre una vez con el último valor.

Códigos de demostración y caja

Shubham Khatri avatar Jan 11 '2018 14:01 Shubham Khatri

TL;DR: Funcional setStatees principalmente útil para esperar una actualización de estado correcta cuando setStatese activan varios mensajes de correo electrónico en un corto intervalo de tiempo, mientras que lo convencional setStatehace la conciliación y podría conducir a un estado inesperado.

Consulte este maravilloso artículo sobre Functional setState para obtener una comprensión clara.

Y aquí está la DEMOSTRACIÓN DE TRABAJO

En primer lugar, estás intentando hacer cosas diferentes en cada uno de tus casos, estás asignando fotografías en uno y concatenando fotografías en otro.

Digamos que this.state.pictures contiene [1, 2, 3]y las fotos contienen[4, 5, 6]

this.setState({pictures: pics})

En el caso anterior, this.state.pictures contendrá las fotografías, es decirthis.state.pictures = [4, 5, 6]

this.setState(prevState => ({
   pictures: prevState.pictures.concat(pics)
}))

Mientras que en el fragmento anterior, this.state.pictures contendrá las imágenes anteriores + fotografías, es decirthis.state.pictures = [1, 2, 3, 4, 5, 6]

De cualquier manera, puede modificarlo para satisfacer sus necesidades de API; si es como una respuesta paginada, es mejor que concatene los resultados en cada solicitud; de lo contrario, si obtiene la matriz completa cada vez, simplemente asígnela.

setState convencional VS setState funcional

Ahora, tu pregunta principal probablemente sea si usarlo setStatecon un objeto o con una función.

La gente usa ambos por diferentes razones, ahora setStatese dice que la funcionalidad es segura porque Reacthace algo llamado proceso de reconciliación en el que fusiona múltiples objetos en su interior setStatecuando se activa con frecuencia o simultáneamente y aplica los cambios de una sola vez, algo así como un proceso por lotes. . Potencialmente, esto podría conducir a algunos resultados inesperados en escenarios como el siguiente.

EJEMPLO:

increaseScoreBy3 () {
 this.setState({score : this.state.score + 1});
 this.setState({score : this.state.score + 1});
 this.setState({score : this.state.score + 1});
}

Como es de esperar, la puntuación se incrementará en 3, pero lo que hace React es fusionar todos los objetos y actualizar la puntuación solo una vez, es decir, incrementarla en 1.

Este es uno de los casos en los que la devolución de llamada funcional brilla porque la conciliación no ocurre en las funciones y la ejecución del siguiente código hará las cosas como se esperaba, es decir, actualizará la puntuación en 3.

increaseScoreBy3 () {
 this.setState(prevState => ({ score: prevState.score + 1 }));
 this.setState(prevState => ({ score: prevState.score + 1 }));
 this.setState(prevState => ({ score: prevState.score + 1 }));
}
Nandu Kalidindi avatar Jan 11 '2018 14:01 Nandu Kalidindi