script react helmet change javascript reactjs state setstate

javascript - helmet - react js change title



¿React mantiene el pedido de actualizaciones de estado? (4)

Esta es en realidad una pregunta bastante interesante, pero la respuesta no debería ser demasiado complicada. Existe este gran artículo sobre medio que tiene una respuesta.

1) Si haces esto

this.setState({ a: true }); this.setState({ b: true });

No creo que haya una situación en la que a sea true b sea false debido al batching por batching .

Sin embargo, si b depende de a entonces podría haber una situación en la que no obtendría el estado esperado.

// assuming this.state = { value: 0 }; this.setState({ value: this.state.value + 1}); this.setState({ value: this.state.value + 1}); this.setState({ value: this.state.value + 1});

Después de que se procesen todas las llamadas anteriores, this.state.value será 1, no 3 como cabría esperar.

Esto se menciona en el artículo: setState accepts a function as its parameter

// assuming this.state = { value: 0 }; this.setState((state) => ({ value: state.value + 1})); this.setState((state) => ({ value: state.value + 1})); this.setState((state) => ({ value: state.value + 1}));

Esto nos dará this.state.value === 3

Sé que React puede realizar actualizaciones de estado de forma asincrónica y por lotes para la optimización del rendimiento. Por lo tanto, nunca puede confiar en el estado que se actualizará después de haber llamado a setState . Pero, ¿puede confiar en React para actualizar el estado en el mismo orden en que se solicita setState

  1. el mismo componente?
  2. diferentes componentes?

Considere hacer clic en el botón en los siguientes ejemplos:

1. ¿Existe alguna posibilidad de que a sea falso yb sea verdadero para:

class Container extends React.Component { constructor(props) { super(props); this.state = { a: false, b: false }; } render() { return <Button onClick={this.handleClick}/> } handleClick = () => { this.setState({ a: true }); this.setState({ b: true }); } }

2. ¿Existe alguna posibilidad de que a sea falso yb sea verdadero para:

class SuperContainer extends React.Component { constructor(props) { super(props); this.state = { a: false }; } render() { return <Container setParentState={this.setState.bind(this)}/> } } class Container extends React.Component { constructor(props) { super(props); this.state = { b: false }; } render() { return <Button onClick={this.handleClick}/> } handleClick = () => { this.props.setParentState({ a: true }); this.setState({ b: true }); } }

Tenga en cuenta que estas son simplificaciones extremas de mi caso de uso. Me doy cuenta de que puedo hacer esto de manera diferente, por ejemplo, actualizando ambos parámetros de estado al mismo tiempo en el ejemplo 1, así como realizando la segunda actualización de estado en una devolución de llamada a la primera actualización de estado en el ejemplo 2. Sin embargo, esta no es mi pregunta, y solo me interesa si hay una forma bien definida de que React realice estas actualizaciones de estado, nada más.

Cualquier respuesta respaldada por documentación es muy apreciada.


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, eso resultará en el equivalente de:

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

batching


Yo trabajo en React.

TLDR:

Pero, ¿puede confiar en React para actualizar el estado en el mismo orden en que se solicita setState?

  • el mismo componente?

Sí.

  • diferentes componentes?

Sí.

El orden de las actualizaciones siempre se respeta. Si ve un estado intermedio "entre" o no depende de si está dentro de un lote o no.

Actualmente (React 16 y anteriores), solo las actualizaciones dentro de los controladores de eventos React se agrupan por defecto . Hay una API inestable para forzar el procesamiento por lotes fuera de los controladores de eventos en casos excepcionales cuando lo necesita.

En futuras versiones (probablemente React 17 y posteriores), React agrupará todas las actualizaciones por defecto para que no tenga que pensar en esto. Como siempre, anunciaremos cualquier cambio al respecto en el blog React y en las notas de la versión.

La clave para comprender esto es que no importa cuántas llamadas a setState() en cuántos componentes realice dentro de un controlador de eventos React , producirán solo una nueva representación al final del evento . Esto es crucial para un buen rendimiento en aplicaciones grandes porque si Child and Parent llama a setState() cuando maneja un evento de clic, no desea volver a representar el Child dos veces.

En ambos ejemplos, las llamadas a setState() ocurren dentro de un controlador de eventos React. Por lo tanto, siempre se colocan juntos al final del evento (y no se ve el estado intermedio).

Las actualizaciones siempre se fusionan superficialmente en el orden en que ocurren . Entonces, si la primera actualización es {a: 10} , la segunda es {b: 20} y la tercera es {a: 30} , el estado representado será {a: 30, b: 20} . La actualización más reciente de la misma clave de estado (por ejemplo, como en mi ejemplo) siempre "gana".

El objeto this.state se actualiza cuando volvemos a representar la interfaz de usuario al final del lote. Entonces, si necesita actualizar el estado en función de un estado anterior (como el incremento de un contador), debe usar la setState(fn) funcional setState(fn) que le proporciona el estado anterior, en lugar de leer de this.state . Si tienes curiosidad sobre el razonamiento de esto, lo expliqué en profundidad en este comentario .

En su ejemplo, no veríamos el "estado intermedio" porque estamos dentro de un controlador de eventos React donde se habilita el procesamiento por lotes (porque React "sabe" cuando salimos de ese evento).

Sin embargo, tanto en React 16 como en versiones anteriores, todavía no hay lotes por defecto fuera de los controladores de eventos React . Entonces, si en su ejemplo tuviéramos un controlador de respuesta AJAX en lugar de handleClick , cada setState() se procesaría inmediatamente a medida que suceda. En este caso, sí, vería un estado intermedio:

promise.then(() => { // We''re not in an event handler, so these are flushed separately. this.setState({a: true}); // Re-renders with {a: true, b: false } this.setState({b: true}); // Re-renders with {a: true, b: true } this.props.setParentState(); // Re-renders the parent });

Sabemos que es inconveniente que el comportamiento sea diferente dependiendo de si estás en un controlador de eventos o no . Esto cambiará en una futura versión de React que agrupará todas las actualizaciones de forma predeterminada (y proporcionará una API opcional para eliminar los cambios sincrónicamente). Hasta que cambiemos el comportamiento predeterminado (potencialmente en React 17), hay una API que puede usar para forzar el procesamiento por lotes :

promise.then(() => { // Forces batching ReactDOM.unstable_batchedUpdates(() => { this.setState({a: true}); // Doesn''t re-render yet this.setState({b: true}); // Doesn''t re-render yet this.props.setParentState(); // Doesn''t re-render yet }); // When we exit unstable_batchedUpdates, re-renders once });

Los controladores de eventos Reaccionar internamente se envuelven en unstable_batchedUpdates por lo que están agrupados de forma predeterminada. Tenga en cuenta que ajustar una actualización en unstable_batchedUpdates dos veces no tiene ningún efecto. Las actualizaciones se vacían cuando salimos de la llamada unstable_batchedUpdates más externa.

Esa API es "inestable" en el sentido de que la eliminaremos cuando el procesamiento por lotes ya esté habilitado de forma predeterminada. Sin embargo, no lo eliminaremos en una versión menor, por lo que puede confiar en él de manera segura hasta React 17 si necesita forzar el procesamiento por lotes en algunos casos fuera de los controladores de eventos React.

En resumen, este es un tema confuso porque React solo se agrupa dentro de los controladores de eventos de forma predeterminada. Esto cambiará en futuras versiones, y el comportamiento será más directo entonces. Pero la solución no es agrupar menos , sino agrupar más por defecto. Eso es lo que vamos a hacer.


como en doc

setState () pone en cola los cambios en el estado del componente y le dice a React que este componente y sus elementos secundarios deben volver a representarse con el estado actualizado. Este es el método principal que utiliza para actualizar la interfaz de usuario en respuesta a los controladores de eventos y las respuestas del servidor.

preformará el cambio como en la cola ( FIFO : primero en entrar, primero en salir) la primera llamada será la primera en preformarse