Estado de componentes (State) en React
Los componentes pueden tener estado (state), que es la parte privada de los datos del componente y se puede utilizar para gestionar datos dinámicos.
El estado solo aplica a componentes de clase, o puede usarse en componentes de función cuando se utilizan los Hooks de React.
React trata los componentes como máquinas de estado (State Machines). Mediante la interacción con el usuario, se logran diferentes estados y luego se renderiza la interfaz de usuario, manteniendo la interfaz coherente con los datos.
En React, solo hay que actualizar el estado del componente y luego volver a renderizar la interfaz de usuario según el nuevo estado (no manipular el DOM).
El siguiente ejemplo crea una clase ES6 que extiende React.Component, y usa this.state en el método render() para modificar la hora actual.
Agrega un constructor de clase para inicializar el estado this.state. Los componentes de clase siempre deben llamar al constructor base con props.
Gestión de estado en componentes de clase
Crear un componente de clase con estado:
Archivo Counter.js
class Counter extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
increment = () => {
this.setState({ count: this.state.count + 1 });
}
render() {
return (
<div>
<p>Count: {this.state.count}</p>
<button onClick={this.increment}>Increment</button>
</div>
);
}
}
export default Counter;
Renderizar este componente en src/index.js:
Ejemplo
import ReactDOM from 'react-dom';
import './index.css';
import Counter from './Counter';
const root = ReactDOM.createRoot(document.getElementById("root"));
// Renderizar el componente Counter
root.render(<Counter />);
Gestión de estado en componentes de función (usando Hooks)
Usando los Hooks de React, se puede usar estado en componentes de función. El Hook más común es useState.
Crear un componente de función con estado:
Archivo Counter.js
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
export default Counter;
Renderizar este componente en src/index.js:
Ejemplo
import ReactDOM from 'react-dom';
import './index.css';
import Counter from './Counter';
const root = ReactDOM.createRoot(document.getElementById("root"));
// Renderizar el componente Counter
root.render(<Counter />);
Ejemplo
Crear un ejemplo de reloj para entender el estado del componente:
Ejemplo de React
Pruébalo »
A continuación, haremos que Clock configure su propio temporizador y se actualice cada segundo.
Agregar métodos de ciclo de vida a la clase
En aplicaciones con muchos componentes, es muy importante liberar los recursos ocupados por los componentes cuando se destruyen.
Cada vez que el componente Clock se carga por primera vez en el DOM, queremos generar un temporizador. Esto se llama en Reactmontaje。
De manera similar, cuando el DOM generado por Clock sea eliminado, también querremos limpiar el temporizador. Esto se llama en Reactdesmontaje。
Podemos declarar métodos especiales en la clase del componente para ejecutar código cuando el componente se monta o desmonta:
Ejemplo de React
Pruébalo »
Análisis del ejemplo:
componentDidMount()ycomponentWillUnmount()Los métodos se denominan hooks del ciclo de vida.
Se ejecuta después de que la salida del componente se renderice en el DOM.componentDidMount()En este hook, podemos configurar un temporizador.
this.timerID es el ID del temporizador. PodemoscomponentWillUnmount()limpiar el temporizador en el hook.
Orden de ejecución del código:
-
Cuando
<Clock />se pasa aReactDOM.render()Cuando React llamaClockal constructor del componente. Dado queClocknecesita mostrar la hora actual, se inicializa con un objeto que contiene la hora actual.this.state. Actualizaremos este estado más tarde. -
Luego React llama al
Clockmétodo del componenterender()render. Así React sabe qué se debe mostrar en la pantalla y luego actualiza el DOM para que coincida conClockla salida de renderizado. -
Cuando
ClockCuando su salida se inserta en el DOM, React llama alcomponentDidMount()hook de ciclo de vida. Dentro de este,Clockel componente pide al navegador configurar un temporizador que llame una vez por segundo atick()。 -
El navegador llama cada segundo a
tick()método. Dentro de este,Clockel componente, mediante un objeto con la hora actual, llama asetState()para programar la actualización de la interfaz. Al llamar asetState(), React sabe que el estado ha cambiado y vuelve a llamar alrender()método para determinar qué mostrar en pantalla. Esta vez,render()en el métodothis.state.dateserá diferente, por lo que la salida renderizada contendrá la hora actualizada y el DOM se actualizará en consecuencia. -
Una vez que
Clockel componente es eliminado del DOM, React llama alcomponentWillUnmount()este hook, y el temporizador se limpiará.
Los datos fluyen de arriba hacia abajo
Ni el componente padre ni el hijo pueden saber si un componente tiene estado o no, y no deberían preocuparse de si un componente se define como una función o como una clase.
Por eso el estado a menudo se denomina local o encapsulado. Ningún otro componente, excepto el que lo posee y lo establece, puede acceder a él.
En el siguiente ejemplo, el componente FormattedDate recibirá el valor date en sus props, y no sabrá si proviene del estado de Clock, de las props de Clock, o si se ingresó manualmente:
Ejemplo de React
Pruébalo »
Esto a menudo se denomina flujo de datos de arriba hacia abajo o unidireccional. Cualquier estado siempre pertenece a algún componente específico, y cualquier dato o interfaz derivado de ese estado solo puede afectar a los componentes que están más abajo en el árbol.
Si imaginas un árbol de componentes como una cascada de props, el estado de cada componente es como una fuente de agua adicional que se conecta en un punto arbitrario, pero también fluye hacia abajo.
Para demostrar que todos los componentes están realmente aislados, podemos crear un componente App que renderice tres Clock:
Ejemplo de React
Pruébalo »
En el ejemplo anterior, cada componente Clock crea su propio temporizador y se actualiza de forma independiente.
En una aplicación React, si un componente tiene estado o no se considera un detalle de implementación del componente que puede cambiar con el tiempo.
Podemos usar componentes sin estado dentro de componentes con estado, y también usar componentes con estado dentro de componentes sin estado.
Otras extensiones