Cuándo usar React setState callback

191

Cuando cambia el estado de un componente de reacción, se llama al método de representación. Por lo tanto, para cualquier cambio de estado, se puede realizar una acción en el cuerpo de los métodos de representación. ¿Hay un caso de uso particular para la devolución de llamada setState entonces?

Sahil Jain
fuente
44
Actualmente no está claro lo que está preguntando. ¿Puedes incluir algún código?
Davin Tryon
2
La devolución de llamada setState es para cualquier cosa que desee hacer después de que el estado se haya definido DEFINITIVAMENTE. Dado que setState es asíncrono, si desea llamar a un fx y ASEGURARSE de que el nuevo estado está cargado, para eso está la devolución de llamada
Jayce444
3
El caso de uso para la devolución de llamada setState es bastante claro. Lo usa cuando desea que se ejecute una función después de que se haya actualizado un estado ESPECÍFICO. Si coloca esta función render(), se ejecutará cada vez que se actualice CUALQUIER estado, lo que probablemente no sea lo que desea. Esto también hará que su código sea menos legible y lógico.
M3RS

Respuestas:

225

Sí lo hay, ya que setStatefunciona de alguna asynchronousmanera. Eso significa que después de llamar a setStatela this.statevariable no se cambia de inmediato. así que si desea realizar una acción inmediatamente después de establecer el estado en una variable de estado y luego devolver un resultado, una devolución de llamada será útil

Considere el siguiente ejemplo

....
changeTitle: function changeTitle (event) {
  this.setState({ title: event.target.value });
  this.validateTitle();
},
validateTitle: function validateTitle () {
  if (this.state.title.length === 0) {
    this.setState({ titleError: "Title can't be blank" });
  }
},
....

Es posible que el código anterior no funcione como se esperaba, ya que la titlevariable puede no haber mutado antes de que se realice la validación. Ahora puede preguntarse si podemos realizar la validación en la render()función en sí, pero sería mejor y más limpio si podemos manejar esto en la función changeTitle, ya que eso haría que su código sea más organizado y comprensible

En este caso, la devolución de llamada es útil

....
changeTitle: function changeTitle (event) {
  this.setState({ title: event.target.value }, function() {
    this.validateTitle();
  });

},
validateTitle: function validateTitle () {
  if (this.state.title.length === 0) {
    this.setState({ titleError: "Title can't be blank" });
  }
},
....

Otro ejemplo será cuando quieras dispatchy acción cuando el estado haya cambiado. querrá hacerlo en una devolución de llamada y no en la render()forma en que se llamará cada vez que se produzca la devolución y, por lo tanto, muchos de estos escenarios son posibles donde necesitará una devolución de llamada.

Otro caso es un API Call

Puede surgir un caso cuando necesita hacer una llamada a la API en función de un cambio de estado particular, si lo hace en el método de representación, se llamará en cada onStatecambio de representación o porque alguna Prop se transfirió a la Child Componentmodificación.

En este caso, querrá usar a setState callbackpara pasar el valor de estado actualizado a la llamada API

....
changeTitle: function (event) {
  this.setState({ title: event.target.value }, () => this.APICallFunction());
},
APICallFunction: function () {
  // Call API with the updated value
}
....
Shubham Khatri
fuente
3
Entiendo que es de naturaleza asíncrona. Mi pregunta era ¿hay algo específico que sólo la devolución de llamada setstate se puede utilizar para que tal vez el cuerpo métodos de hacer posible que no soporte (Algo aparte de decir que vamos a código de una mejor legibilidad.)
Sahil Jain
@SahilJain Validation es el ejemplo correcto, no querrá manejarlo en la función render () porque entonces se llamará cada vez que realice algún cambio en el render (), solo querrá llamarlo cuando solo cambie la entrada y, por lo tanto, en la función misma
Shubham Khatri
Reaccionar prohíbe cambiar el estado durante el renderizado. Por lo tanto, es correcto poner la validación en la devolución de llamada.
webdeb
if (this.title.length === 0) {debería ser this.state.title.length, ¿verdad?
Dmitry Minkovsky
44
El primer caso de uso probablemente no sea una buena idea. Las devoluciones de llamada setState se activan después de volver a renderizar, por lo que está causando un doble render sin una buena razón. Este es exactamente el propósito del argumento de la función (actualizador). Simplemente puede ejecutar setState(state => state.title.length ? { titleError: "Title can't be blank" } : null)y el cambio se acumulará. No se requieren dobles renders.
R Esmond
47
this.setState({
    name:'value' 
},() => {
    console.log(this.state.name);
});
Araz Babayev
fuente
14
Gracias por este fragmento de código, que puede proporcionar una ayuda limitada e inmediata. Una explicación adecuada mejoraría en gran medida su valor a largo plazo al mostrar por qué esta es una buena solución al problema y lo haría más útil para futuros lectores con otras preguntas similares. Por favor, editar su respuesta a añadir un poco de explicación, incluyendo los supuestos realizados.
Machavity
1
Cuando desee llamar a una función después del cambio de estado, puede usar el método.
Araz Babayev
¿Qué pasa si desea establecer múltiples propiedades de estado como nombre, nombre, etc.?
Sumanth Varada
44

1. El caso de uso que viene a mi mente, es una apillamada, que no debería entrar en el render, porque se ejecutará para un eachcambio de estado. Y la llamada a la API solo debe realizarse en un cambio de estado especial, y no en cada render.

changeSearchParams = (params) => {
  this.setState({ params }, this.performSearch)
} 

performSearch = () => {
  API.search(this.state.params, (result) => {
    this.setState({ result })
  });
}

Por lo tanto, para cualquier cambio de estado, se puede realizar una acción en el cuerpo de los métodos de representación.

Muy mala práctica , debido a que el rendermétodo-debe ser puro, significa que no se deben realizar acciones, cambios de estado, llamadas a la API, solo componga su vista y devuélvala. Las acciones deben realizarse solo en algunos eventos. Render no es un evento, sino componentDidMountpor ejemplo.

webdeb
fuente
25

Considere la llamada setState

this.setState({ counter: this.state.counter + 1 })

IDEA

Se puede llamar a setState en función asíncrona

Por lo tanto, no puede confiar this. Si la llamada anterior se realizó dentro de una función asincrónica, thisse referirá al estado del componente en ese punto de tiempo, pero esperábamos que esto se refiriera a la propiedad dentro del estado en la llamada setState del tiempo o al comienzo de la tarea asincrónica. Y como la tarea era llamada asincrónica, esa propiedad puede haber cambiado con el tiempo. Por lo tanto, no es confiable usar thispalabras clave para referirse a alguna propiedad de estado, por lo tanto, usamos la función de devolución de llamada cuyos argumentos son anteriorState y props, lo que significa que cuando se realizó la tarea asincrónica y que era hora de actualizar el estado usando setState, la llamada anteriorState se referirá al estado ahora cuando setState aún no ha comenzado Garantizar la fiabilidad de que nextState no se corromperá.

Código incorrecto: conduciría a la corrupción de datos

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

Código correcto con setState con función de devolución de llamada:

 this.setState(
       (prevState,props)=>{
           return {counter:prevState.counter+1};
        }
    );

Por lo tanto, cada vez que necesitemos actualizar nuestro estado actual al siguiente estado en función del valor presentado por la propiedad en este momento y todo esto está sucediendo de manera asíncrona, es una buena idea usar setState como función de devolución de llamada.

He tratado de explicarlo en codepen aquí CODE PEN

Aniket Jha
fuente