Cuándo usar setState funcional

He estado aprendiendo React en los últimos días, mirando algunos tutoriales y explicaciones sobre las diferentes formas en que puede escribir diferentes elementos. Sin embargo, hay uno que me ha setState la setState función setState para actualizar / anular las propiedades de state 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 { 
{this.state.pictures}
} } }

Este ejemplo me permite buscar imágenes de una API.

Dado que he realizado mi búsqueda, mapa y regreso para esta función, entonces actualizaré las pictures: [] estado de la matriz con los resultados obtenidos en la llamada API.

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

Lo he visto escrito de 2 maneras 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 he visto que se describe como un método más seguro

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

¿Podría alguien explicar los méritos de usar cualquiera? Quiero ser coherente con el código en el futuro, tratar con accesorios y estados, etc., por lo que el método más versátil sería, por supuesto, preferido.

Lo primero es lo primero, en tu caso las dos syntax son completamente diferentes, lo que podrías estar buscando es la diferencia entre

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

y

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

Para entender por qué el segundo método es uno prefijado, debe comprender lo que React hace con setState internamente.

React fusionará primero el objeto que pasó con setState() en el estado actual. Entonces comenzará esa cosa de reconciliación. Debido a la llamada a setState() podría no actualizar su estado inmediatamente.

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

Considere el caso simple, para entender esto, en su función puede llamar a 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)}) ... } 

que no es un caso de uso válido en una aplicación simple, pero a medida que la aplicación se vuelve más compleja, múltiples llamadas a setState pueden estar ocurriendo desde múltiples lugares, haciendo lo mismo.

Así que ahora para realizar una actualización eficiente, React realiza la operación de procesamiento por lotes extrayendo todos los objetos pasados ​​a cada llamada setState() , los fusiona para formar un solo objeto y luego usa ese único objeto para hacer setState() . De acuerdo con la documentación de setState

Si intenta incrementar una cantidad de 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 anterior, recomendamos usar el formulario de función de actualización, en su lugar

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 solo ocurre una vez con el último valor

Demo Codesandbox

TL; DR: Functional setState es principalmente útil para esperar la actualización de estado correcta cuando se desencadenan múltiples setState s en un corto intervalo de tiempo donde el setState convencional hace la reconciliación y puede conducir a un estado inesperado.

Por favor, consulte este maravilloso artículo sobre Functional setState para obtener una comprensión clara

Y aquí está la DEMO DE TRABAJO

En primer lugar, estás tratando de hacer cosas diferentes en cada uno de tus casos, estás asignando fotos en una y concatenando fotos en otra.

Digamos esto.state.pictures contains [1, 2, 3] y las fotos contienen [4, 5, 6]

this.setState({pictures: pics})

En el caso anterior, this.state.pictures contendrá las imágenes, es decir this.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 previas + imágenes, es decir this.state.pictures = [1, 2, 3, 4, 5, 6]

De cualquier manera, puede ajustarlo para cumplir con sus necesidades API, si es como una respuesta paginada, es mejor concatenar los resultados en cada solicitud, de lo contrario, si obtiene la matriz completa, solo asigne toda la matriz.

SetState convencional VS Conjunto funcionalState

Ahora, su pregunta principalmente es si usar setState con un objeto o con una función.

Las personas los usan por diferentes razones, ahora se dice que el setState funcional es seguro porque React hace algo llamado proceso de reconciliación donde fusiona varios objetos dentro de setState cuando se activa frecuentemente o al mismo tiempo y aplica los cambios en una sola toma, algo así como un proceso por lotes Esto podría conducir a algunos resultados inesperados en escenarios como a continuación.

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 React hace es fusionar todos los objetos y actualizar la puntuación solo una vez, es decir, boostla en 1

Este es uno de los casos en que la callback funcional brilla porque la reconciliación no ocurre en las funciones y la ejecución del código a continuación hará las cosas como se espera, 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 })); }