Atención

Recomendamos definir los componentes como funciones en lugar de clases. Mira cómo migrar.

Component es la clase base para los componentes de React definidos como clases en JavaScript. Los componentes de clase aún son compatibles con React, pero no recomendamos usarlos en nuevo código.

class Greeting extends Component {
render() {
return <h1>Hola, {this.props.name}!</h1>;
}
}

Referencia

Component

Para definir un componente de React como clase, se debe extender la clase incorporada Component y definir un método render.

import { Component } from 'react';

class Greeting extends Component {
render() {
return <h1>Hola, {this.props.name}!</h1>;
}
}

Sólo el método render es requerido, otros métodos son opcionales.

Ver más ejemplos abajo.


context

El contexto de un componente de clase está disponible como this.context. Solo está disponible si especificas cual contexto deseas recibir usando static contextType (moderno) o static contextTypes (deprecado).

Un componente de clase solo puede leer un contexto a la vez.

class Button extends Component {
static contextType = ThemeContext;

render() {
const theme = this.context;
const className = 'button-' + theme;
return (
<button className={className}>
{this.props.children}
</button>
);
}
}

Nota

Leer this.context en componentes de clase es equivalente a usar useContext en componentes de función.

Mira cómo migrar.


props

Las props que se pasan a un componente de clase están disponibles como this.props.

class Greeting extends Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}

<Greeting name="Taylor" />

Nota

Leer this.props en componentes de clase es equivalente a declarar props en componentes de función.

Mira cómo migrar.


refs

Obsoleto

Esta API será eliminada en una versión mayor futura de React. Usa createRef en su lugar.

Te permite acceder a legacy string refs para este componente.


state

El estado de un componente de clase está disponible como this.state. El campo state debe ser un objeto. No mutes el estado directamente. Si deseas cambiar el estado, llama a setState con el nuevo estado.

class Counter extends Component {
state = {
age: 42,
};

handleAgeChange = () => {
this.setState({
age: this.state.age + 1
});
};

render() {
return (
<>
<button onClick={this.handleAgeChange}>
Incrementar edad
</button>
<p>Tienes {this.state.age} años.</p>
</>
);
}
}

Nota

Definir state en los componentes de clase es equivalente a llamar a useState en los componentes de función.

Mira cómo migrar.


constructor(props)

El constructor se ejecuta antes de que el componente de clase se monte (se agregue a la pantalla). Normalmente, en React se utiliza el constructor únicamente para dos propósitos. Te permite declarar el estado y enlazar los métodos de la clase con la instancia de la clase:

class Counter extends Component {
constructor(props) {
super(props);
this.state = { counter: 0 };
this.handleClick = this.handleClick.bind(this);
}

handleClick() {
// ...
}

Si usas la sintaxis moderna de JavaScript, rara vez se necesitan constructores. En su lugar, puedes reescribir este código usando la sintaxis de campo de clase pública que es compatible tanto con navegadores modernos como con herramientas como Babel:

class Counter extends Component {
state = { counter: 0 };

handleClick = () => {
// ...
}

Un constructor no debería tener efectos secundarios ni suscripciones.

Parámetros

  • props: Las props iniciales del componente.

Retorna

El constructor no debe retornar nada.

Precauciones

  • No ejecutes ningún efecto secundario o suscripciones en el constructor. En su lugar, utiliza componentDidMount para eso.

  • Dentro de un constructor, debes llamar a super(props) antes que cualquier otra declaración. Si no lo haces, this.props será undefined mientras se ejecuta el constructor, lo que puede ser confuso y causar errores.

  • El constructor es el único lugar donde puedes asignar this.state directamente. En todos los demás métodos, debes utilizar this.setState() en su lugar. No llames a setState en el constructor.

  • Cuando usas renderizado en el servidor, el constructor también se ejecutará en el servidor, seguido del método render. Sin embargo, los métodos del ciclo de vida como componentDidMount o componentWillUnmount no se ejecutarán en el servidor.

  • Cuando Strict Mode está activado, React llamará al constructor dos veces en desarrollo y luego descartará una de las instancias. Esto ayuda a notar los efectos secundarios accidentales que deben moverse fuera del constructor.

Nota

No hay una equivalencia exacta para constructor en los componentes de función. Para declarar el estado en un componente de función, llama a useState. Para evitar recalcular el estado inicial, pasa una función a useState.


componentDidCatch(error, info)

Si defines componentDidCatch, React lo llamará cuando algún componente hijo (incluso los distantes) lance un error durante el renderizado. Esto te permite registrar ese error en un servicio de reporte de errores en producción.

Normalmente, se utiliza junto con static getDerivedStateFromError, lo que te permite actualizar el estado en respuesta a un error y mostrar un mensaje de error al usuario. Un componente con estos métodos se llama error boundary.

Ver un ejemplo.

Parámetros

  • error: El error que fue lanzado. En la práctica, generalmente será una instancia de Error, pero no se garantiza ya que JavaScript permite lanzar cualquier valor, incluyendo cadenas de texto o incluso null.

  • info: Un objeto que contiene información adicional sobre el error. Su campo componentStack contiene una pila de rastreo con el componente que lanzó el error, así como los nombres y ubicaciones de origen de todos sus componentes padres. En producción, los nombres de los componentes se reducirán. Si configuras la notificación de errores en producción, puedes decodificar la pila de componentes utilizando sourcemaps de la misma manera que lo harías con las pilas de errores regulares de JavaScript.

Retorna

componentDidCatch no debería retornar nada.

Precauciones

  • En el pasado, era común llamar a setState dentro de componentDidCatch para actualizar la interfaz de usuario y mostrar un mensaje de error alternativo. Esto está obsoleto a favor de definir static getDerivedStateFromError.

  • Las versiones de producción y desarrollo de React difieren ligeramente en la forma en que componentDidCatch maneja los errores. En desarrollo, los errores se propagarán a window, lo que significa que cualquier window.onerror o window.addEventListener('error', callback) interceptará los errores capturados por componentDidCatch. En producción, en cambio, los errores no se propagarán, lo que significa que cualquier administrador de errores principal solo recibirá errores no capturados explícitamente por `componentDidCatch.

Nota

Aún no hay un equivalente directo para componentDidCatch en componentes de función. Si deseas evitar crear componentes de clase, puedes escribir un solo componente ErrorBoundary como se menciona arriba y usarlo en toda tu aplicación. Alternativamente, puedes usar el paquete react-error-boundary que lo hace por ti.


componentDidMount()

Si defines el método componentDidMount, React lo llamará cuando tu componente se agregue por primera vez (se monte) en la pantalla. Este es un lugar común para comenzar la obtención de datos, configurar suscripciones o manipular los nodos del DOM.

Si implementas componentDidMount, generalmente debes implementar otros métodos del ciclo de vida para evitar errores. Por ejemplo, si componentDidMount lee algún estado o propiedades, también debes implementar componentDidUpdate para manejar sus cambios, y componentWillUnmount para limpiar lo que componentDidMount estaba haciendo.

class ChatRoom extends Component {
state = {
serverUrl: 'https://localhost:1234'
};

componentDidMount() {
this.setupConnection();
}

componentDidUpdate(prevProps, prevState) {
if (
this.props.roomId !== prevProps.roomId ||
this.state.serverUrl !== prevState.serverUrl
) {
this.destroyConnection();
this.setupConnection();
}
}

componentWillUnmount() {
this.destroyConnection();
}

// ...
}

Ver más ejemplos.

Parámetros

componentDidMount no toma ningún parámetro.

Retorna

componentDidMount no debería devolver nada.

Precauciones

  • Cuando se activa el modo estricto, en desarrollo React llamará a componentDidMount, luego inmediatamente llamará a componentWillUnmount y luego llamará a componentDidMount nuevamente. Esto te ayuda a notar si olvidaste implementar componentWillUnmount o si su lógica no refleja completamente lo que hace componentDidMount.

  • Aunque puedes llamar a setState inmediatamente en componentDidMount, es mejor evitarlo siempre que puedas. Esto provocará un renderizado adicional, pero sucederá antes de que el navegador actualice la pantalla. Esto garantiza que aunque render se llame dos veces en este caso, el usuario no verá el estado intermedio. Usa este patrón con precaución porque a menudo causa problemas de rendimiento. En la mayoría de los casos, deberías ser capaz de asignar el estado inicial en el constructor en su lugar. Sin embargo, puede ser necesario en casos como modales y tooltips cuando necesitas medir un nodo DOM antes de renderizar algo que depende de su tamaño o posición.

Nota

Para muchos casos de uso, definir componentDidMount, componentDidUpdate y componentWillUnmount juntos en componentes de clase es equivalente a llamar a useEffect en componentes funcionales. En los casos raros donde es importante que el código se ejecute antes de renderizarse en el navegador, useLayoutEffect es una opción más adecuada.

Mira cómo migrar.


componentDidUpdate(prevProps, prevState, snapshot?)

Si defines el método componentDidUpdate, React lo llamará inmediatamente después de que tu componente haya sido renderizado de nuevo con las props o el estado actualizado. Este método no se llama para el renderizado inicial.

Puedes utilizarlo para manipular el DOM después de una actualización. También es un lugar común para hacer solicitudes de red siempre y cuando compares las props actuales con las props anteriores (por ejemplo, una solicitud de red puede no ser necesaria si las props no han cambiado). Normalmente, lo usarías junto con componentDidMount y componentWillUnmount:

class ChatRoom extends Component {
state = {
serverUrl: 'https://localhost:1234'
};

componentDidMount() {
this.setupConnection();
}

componentDidUpdate(prevProps, prevState) {
if (
this.props.roomId !== prevProps.roomId ||
this.state.serverUrl !== prevState.serverUrl
) {
this.destroyConnection();
this.setupConnection();
}
}

componentWillUnmount() {
this.destroyConnection();
}

// ...
}

Ver más ejemplos.

Parámetros

  • prevProps: Las props antes de la actualización. Compara prevProps con this.props para determinar lo que cambió.

  • prevState: El estado antes de la actualización. Compara prevState con this.state para determinar lo que cambió.

  • snapshot: Si implementaste getSnapshotBeforeUpdate, snapshot contendrá el valor que retornaste desde ese método. De lo contrario, será undefined.

Retorna

componentDidUpdate no debería devolver nada.

Precauciones

  • componentDidUpdate no será llamado si shouldComponentUpdate está definido y devuelve false.

  • La lógica dentro de componentDidUpdate generalmente debería estar envuelta en condiciones que comparan this.props con prevProps y this.state con prevState. De lo contrario, existe el riesgo de crear bucles infinitos.

  • Aunque puedes llamar setState inmediatamente en componentDidUpdate, es mejor evitarlo siempre que puedas. Desencadenará una representación adicional, pero sucederá antes de que el navegador actualice la pantalla. Esto garantiza que aunque render se llamará dos veces en este caso, el usuario no verá el estado intermedio. Este patrón a menudo causa problemas de rendimiento, pero puede ser necesario para casos raros como modales y tooltips cuando necesita medir un nodo DOM antes de renderizar algo que depende de su tamaño o posición.

Nota

Para muchos casos de uso, definir juntos componentDidMount, componentDidUpdate y componentWillUnmount en componentes de clase es equivalente a llamar a useEffect en componentes de función. En los casos raros donde es importante que el código se ejecute antes de renderizar en el navegador, useLayoutEffect es una opción más cercana.

Mira cómo migrar.


componentWillMount()

Obsoleto

Esta API ha sido renombrado de componentWillMount a UNSAFE_componentWillMount. El nombre antiguo ha sido deprecado. En una versión importante futura de React, solo funcionará el nuevo nombre.

Ejecuta rename-unsafe-lifecycles codemod para actualizar automáticamente sus componentes.


componentWillReceiveProps(nextProps)

Obsoleto

Esta API ha sido renombrada de componentWillReceiveProps a UNSAFE_componentWillReceiveProps. El nombre antiguo ha sido deprecado. En una versión mayor futura de React, solo funcionará el nuevo nombre.

Ejecuta rename-unsafe-lifecycles codemod para actualizar automáticamente tus componentes.


componentWillUpdate(nextProps, nextState)

Obsoleto

Esta API ha sido renombrada de componentWillUpdate a UNSAFE_componentWillUpdate. El nombre antiguo ha sido desaprobado. En una versión mayor futura de React, solo funcionará el nuevo nombre.

Ejecuta rename-unsafe-lifecycles codemod para actualizar automáticamente tus componentes.


componentWillUnmount()

Si defines el método componentWillUnmount, React lo llamará antes de que tu componente sea eliminado (desmontado) de la pantalla. Este es un lugar común para cancelar la obtención de datos o eliminar suscripciones.

La lógica dentro de componentWillUnmount debe «reflejar» la lógica dentro de componentDidMount. Por ejemplo, si componentDidMount configura una suscripción, componentWillUnmount debe limpiar esa suscripción. Si la lógica de limpieza en componentWillUnmount lee algunas props o estado, generalmente también deberás implementar componentDidUpdate para limpiar recursos (como suscripciones) correspondientes a las props y estados antiguos.

class ChatRoom extends Component {
state = {
serverUrl: 'https://localhost:1234'
};

componentDidMount() {
this.setupConnection();
}

componentDidUpdate(prevProps, prevState) {
if (
this.props.roomId !== prevProps.roomId ||
this.state.serverUrl !== prevState.serverUrl
) {
this.destroyConnection();
this.setupConnection();
}
}

componentWillUnmount() {
this.destroyConnection();
}

// ...
}

Ver más ejemplos.

Parámetros

componentWillUnmount no recibe ningún parámetro.

Retorna

componentWillUnmount no debería devolver nada.

Precauciones

  • Cuando el Modo Estricto está activado, en desarrollo React llamará a componentDidMount y luego llamará inmediatamente a componentWillUnmount, y luego llamará a componentDidMount de nuevo. Esto ayuda a notar si olvidaste implementar componentWillUnmount o si su lógica no refleja completamente lo que hace componentDidMount.

Nota

Para muchos casos de uso, definir componentDidMount, componentDidUpdate y componentWillUnmount juntos en componentes de clase es equivalente a llamar a useEffect en componentes de función. En los casos raros donde es importante que el código se ejecute antes de la pintura del navegador, useLayoutEffect es más adecuado.

Consulta cómo migrar.


forceUpdate(callback?)

forceUpdate fuerza a un componente a volver a renderizarse.

Por lo general, esto no es necesario. Si el método render de tu componente solo lee de this.props, this.state o this.context, se volverá a renderizar automáticamente cuando llames a setState dentro de tu componente o uno de sus padres. Sin embargo, si el método render de tu componente lee directamente de una fuente de datos externa, debes indicarle a React que actualice la interfaz de usuario cuando cambie esa fuente de datos. Para eso sirve forceUpdate.

Trata de evitar todas las situaciones donde se necesita utilizar forceUpdate y solo lee de this.props y this.state en render.

Parámetros

  • opcional callback Si se especifica, React llamará al callback que hayas proporcionado después de que se haya realizado la actualización.

Retorna

forceUpdate no devuelve nada.

Precauciones

Nota

La lectura de una fuente de datos externa y la actualización forzada de componentes de clase en respuesta a sus cambios con forceUpdate ha sido reemplazada por useSyncExternalStore en componentes de función.


getChildContext()

Obsoleto

Esta API será eliminada en una versión importante futura de React. Usa en su lugar Context.Provider.

Permite especificar los valores para el contexto heredado que es proporcionado por este componente.


getSnapshotBeforeUpdate(prevProps, prevState)

Si implementas getSnapshotBeforeUpdate, React lo llamará inmediatamente antes de actualizar el DOM. Esto permite que tu componente capture cierta información del DOM (por ejemplo, la posición de desplazamiento) antes de que potencialmente cambie. Cualquier valor devuelto por este método de ciclo de vida se pasará como parámetro a componentDidUpdate.

Por ejemplo, puedes usarlo en una interfaz de usuario como un hilo de chat que necesita conservar su posición de desplazamiento durante las actualizaciones:

class ScrollingList extends React.Component {
constructor(props) {
super(props);
this.listRef = React.createRef();
}

getSnapshotBeforeUpdate(prevProps, prevState) {
// Are we adding new items to the list?
// Capture the scroll position so we can adjust scroll later.
if (prevProps.list.length < this.props.list.length) {
const list = this.listRef.current;
return list.scrollHeight - list.scrollTop;
}
return null;
}

componentDidUpdate(prevProps, prevState, snapshot) {
// If we have a snapshot value, we've just added new items.
// Adjust scroll so these new items don't push the old ones out of view.
// (snapshot here is the value returned from getSnapshotBeforeUpdate)
if (snapshot !== null) {
const list = this.listRef.current;
list.scrollTop = list.scrollHeight - snapshot;
}
}

render() {
return (
<div ref={this.listRef}>{/* ...contents... */}</div>
);
}
}

En el ejemplo anterior, es importante leer la propiedad scrollHeight directamente en getSnapshotBeforeUpdate. No es seguro leerla en render, UNSAFE_componentWillReceiveProps o UNSAFE_componentWillUpdate porque existe un posible lapso de tiempo entre la llamada a estos métodos y la actualización del DOM por parte de React.

Parámetros

  • prevProps: Props antes de la actualización. Compara prevProps con this.props para determinar lo que cambió.

  • prevState: Estado antes de la actualización. Compara prevState con this.state para determinar lo que cambió.

Retorna

Deberías devolver un valor de instantánea de cualquier tipo que desees o null. El valor que devuelvas se pasará como tercer argumento a componentDidUpdate.

Precauciones

getSnapshotBeforeUpdate no se llamará si se define shouldComponentUpdate y devuelve false.

Nota

Actualmente, no hay un equivalente a getSnapshotBeforeUpdate para componentes de función. Este caso de uso es muy poco común, pero si lo necesitas, por ahora tendrás que escribir un componente de clase.


render()

El método render es el único método requerido en un componente de clase.

El método render debería especificar lo que deseas que aparezca en la pantalla, por ejemplo:

import { Component } from 'react';

class Greeting extends Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}

React puede llamar a render en cualquier momento, por lo que no debes asumir que se ejecuta en un momento determinado. Por lo general, el método render debería devolver una pieza de JSX, pero se admiten algunos otros tipos de retorno (como cadenas). Para calcular el JSX devuelto, el método render puede leer this.props, this.state y this.context.

Deberías escribir el método render como una función pura, lo que significa que debería devolver el mismo resultado si las props, el estado y el contexto son iguales. Tampoco debería contener efectos secundarios (como configurar suscripciones) o interactuar con las API del navegador. Los efectos secundarios deberían ocurrir en controladores de eventos o en métodos como componentDidMount.

Parámetros

  • prevProps: Props anteriores a la actualización. Compara prevProps con this.props para determinar qué cambió.

  • prevState: Estado anterior a la actualización. Compara prevState con this.state para determinar qué cambió.

Retorna

render puede devolver cualquier nodo React válido. Esto incluye elementos React como <div />, cadenas de texto, números, portales, nodos vacíos (null, undefined, true y false), y arrays de nodos de React.

Precauciones

  • render debe ser escrito como una función pura de props, state, y context. No debe tener efectos secundarios.
  • render no será llamado si shouldComponentUpdate está definido y devuelve false.
  • Cuando Strict Mode está activado, React llamará a render dos veces en desarrollo y luego descartará uno de los resultados. Esto te ayuda a notar los efectos secundarios accidentales que necesitan ser movidos fuera del método render.
  • No hay una correspondencia uno a uno entre la llamada a render y la posterior llamada a componentDidMount o componentDidUpdate. Algunos de los resultados de la llamada a render pueden ser descartados por React cuando es beneficioso.

setState(nextState, callback?)

Llama a setState para actualizar el estado de tu componente React.

class Form extends Component {
state = {
name: 'Taylor',
};

handleNameChange = (e) => {
const newName = e.target.value;
this.setState({
name: newName
});
}

render() {
return (
<>
<input value={this.state.name} onChange={this.handleNameChange} />
<p>Hello, {this.state.name}.
</>
);
}
}

setState encola cambios en el estado del componente. Le dice a React que este componente y sus hijos necesitan volver a renderizarse con el nuevo estado. Esta es la forma principal en la que actualizará la interfaz de usuario en respuesta a interacciones.

Atención

Llamar a setState no cambia el estado actual en el código que ya se está ejecutando:

function handleClick() {
console.log(this.state.name); // "Taylor"
this.setState({
name: 'Robin'
});
console.log(this.state.name); // Still "Taylor"!
}

Solo afecta lo que this.state devolverá a partir del siguiente renderizado.

También puedes pasar una función a setState. Esto te permite actualizar el estado basándote en el estado anterior:

handleIncreaseAge = () => {
this.setState(prevState => {
return {
age: prevState.age + 1
};
});
}

No es necesario hacer esto, pero es útil si desea actualizar el estado varias veces durante el mismo evento.

Parámetros

  • nextState: Puede ser un objeto o una función.

    • Si pasa un objeto como nextState, se fusionará superficialmente en this.state.
    • Si pasa una función como nextState, se tratará como una función de actualización. Debe ser pura, debe tomar como argumentos el estado pendiente y las props, y debe devolver el objeto que se fusionará superficialmente en this.state. React pondrá su función de actualización en una cola y volverá a renderizar su componente. Durante el próximo renderizado, React calculará el siguiente estado aplicando todas las actualizaciones en cola al estado anterior.
  • opcional callback: Si se especifica, React llamará al callback que ha proporcionado después de que se haya confirmado la actualización.

Retorna

setState no devuelve nada.

Precauciones

  • Piensa en setState como una solicitud en lugar de un comando inmediato para actualizar el componente. Cuando varios componentes actualizan su estado en respuesta a un evento, React los agrupa y los renderiza juntos en una sola pasada al final del evento. En el caso raro de que necesites forzar que una actualización de estado en particular se aplique de forma sincrónica, puedes envolverla en flushSync, pero esto puede afectar el rendimiento.

  • setState no actualiza this.state inmediatamente. Esto puede ser un problema potencial si se lee this.state justo después de llamar a setState. En su lugar, utiliza componentDidUpdate o el argumento de callback de setState, ya que ambos están garantizados para activarse después de que se haya aplicado la actualización. Si necesitas establecer el estado basado en el estado anterior, puedes pasar una función a nextState como se describe anteriormente.

Nota

Llamar a setState en componentes de clase es similar a llamar a una función set en componentes funcionales.

Mira cómo migrar.


shouldComponentUpdate(nextProps, nextState, nextContext)

Si defines shouldComponentUpdate, React lo llamará para determinar si se puede omitir una nueva representación.

Si estás seguro de que quieres escribirlo a mano, puedes comparar this.props con nextProps y this.state con nextState y devolver false para indicar a React que se puede omitir la actualización.

class Rectangle extends Component {
state = {
isHovered: false
};

shouldComponentUpdate(nextProps, nextState) {
if (
nextProps.position.x === this.props.position.x &&
nextProps.position.y === this.props.position.y &&
nextProps.size.width === this.props.size.width &&
nextProps.size.height === this.props.size.height &&
nextState.isHovered === this.state.isHovered
) {
// Nothing has changed, so a re-render is unnecessary
return false;
}
return true;
}

// ...
}

React llama a shouldComponentUpdate antes de renderizar cuando se reciben nuevas props o estado. Por defecto, devuelve true. Este método no se llama para la renderización inicial o cuando se usa forceUpdate.

Parámetros

  • nextProps: Las próximas props que el componente está a punto de renderizar. Compare nextProps con this.props para determinar lo que cambió.
  • nextState: El próximo estado con el que el componente está a punto de renderizar. Compare nextState con this.state para determinar lo que cambió.
  • nextContext: El próximo contexto con el que el componente está a punto de renderizar. Compare nextContext con this.context para determinar lo que cambió. Solo está disponible si se especifica static contextType (moderno) o static contextTypes (legado).

Retorna

Devuelve true si quieres que el componente se vuelva a renderizar. Ese es el comportamiento predeterminado.

Devuelve false para indicar a React que se puede omitir la re-renderización.

Precauciones

  • Este método solo existe como una optimización de rendimiento. Si su componente falla sin él, primero solucione eso.

  • Considera usar PureComponent en lugar de escribir shouldComponentUpdate manualmente. PureComponent compara superficialmente las props y el estado, y reduce la posibilidad de que omita una actualización necesaria.

  • No recomendamos hacer verificaciones de igualdad profunda o usar JSON.stringify en shouldComponentUpdate. Esto hace que el rendimiento sea impredecible y dependa de la estructura de datos de cada prop y estado. En el mejor de los casos, corre el riesgo de introducir paradas de varios segundos en su aplicación, y en el peor de los casos, corre el riesgo de que se bloquee.

  • Devolver false no impide que los componentes secundarios se vuelvan a renderizar cuando cambia su estado.

  • Devolver false no garantiza que el componente no se volverá a renderizar. React utilizará el valor de retorno como una sugerencia, pero aún puede elegir volver a renderizar el componente si tiene sentido hacerlo por otras razones.

Nota

Optimizar componentes de clase con shouldComponentUpdate es similar a optimizar componentes de función con memo. Los componentes de función también ofrecen una optimización más granular con useMemo.


UNSAFE_componentWillMount()

Si defines UNSAFE_componentWillMount, React lo llamará inmediatamente después del constructor. Solo existe por razones históricas y no debe usarse en ningún código nuevo. En su lugar, usa una de las alternativas:

  • Para inicializar el estado, declara state como un campo de clase o establece this.state dentro del constructor.
  • Si necesitas ejecutar un efecto secundario o configurar una suscripción, mueve esa lógica a componentDidMount en su lugar.

Ver ejemplos de migración de los ciclos de vida inseguros.

Parámetros

UNSAFE_componentWillMount no acepta ningún parámetro.

Retorna

UNSAFE_componentWillMount no debería retornar nada.

Precauciones

  • UNSAFE_componentWillMount no se llamará si el componente implementa static getDerivedStateFromProps o getSnapshotBeforeUpdate.

  • A pesar de su nombre, UNSAFE_componentWillMount no garantiza que el componente se montará si su aplicación usa características modernas de React como Suspense. Si se suspende un intento de renderizado (por ejemplo, porque el código de algún componente hijo aún no se ha cargado), React descartará el árbol en progreso y tratará de construir el componente desde cero durante el próximo intento. Por eso, este método es «inseguro». El código que depende del montaje (como agregar una suscripción) debe ir en componentDidMount.

  • UNSAFE_componentWillMount es el único método del ciclo de vida que se ejecuta durante renderizado en el servidor. Para todos los propósitos prácticos, es idéntico al constructor, por lo que debería usar el constructor para este tipo de lógica en su lugar.

Nota

Llamar a setState dentro de UNSAFE_componentWillMount en un componente de clase para inicializar el estado es equivalente a pasar ese estado como estado inicial a useState en un componente de función.


UNSAFE_componentWillReceiveProps(nextProps, nextContext)

Si defines UNSAFE_componentWillReceiveProps, React lo llamará cuando el componente reciba nuevas props. Solo existe por razones históricas y no se debe usar en ningún código nuevo. En su lugar, utiliza una de las siguientes alternativas:

  • Si necesitas realizar un efecto secundario (por ejemplo, buscar datos, ejecutar una animación o volver a inicializar una suscripción) en respuesta a cambios en las props, mueve esa lógica a componentDidUpdate en su lugar.
  • Si necesitas evitar volver a calcular algunos datos solo cuando cambia una prop, utiliza un ayudante de memoización en su lugar.
  • Si necesitas «restablecer» algunos estados cuando cambia una prop, considera hacer que un componente sea totalmente controlado o totalmente no controlado con una clave en su lugar.
  • Si necesitas «ajustar» algunos estados cuando cambia una prop, comprueba si puedes calcular toda la información necesaria solo a partir de las props durante la renderización. Si no puedes, utiliza static getDerivedStateFromProps en su lugar.

Ver ejemplos de migración de ciclos de vida inseguros.

Parámetros

  • nextProps: Las próximas props que el componente está a punto de recibir de su componente padre. Compara nextProps con this.props para determinar qué ha cambiado.
  • nextContext: El próximo contexto que el componente está a punto de recibir del proveedor más cercano. Compara nextContext con this.context para determinar qué ha cambiado. Solo está disponible si se especifica static contextType (moderno) o static contextTypes (legado).

Retorna

UNSAFE_componentWillReceiveProps no debe devolver nada.

Precauciones

  • UNSAFE_componentWillReceiveProps no se llamará si el componente implementa static getDerivedStateFromProps o getSnapshotBeforeUpdate.

  • A pesar de su nombre, UNSAFE_componentWillReceiveProps no garantiza que el componente recibirá esas props si tu aplicación utiliza características modernas de React como Suspense. Si un intento de renderizado se suspende (por ejemplo, porque el código para algún componente hijo aún no se ha cargado), React descarta el árbol en progreso e intenta construir el componente desde cero durante el próximo intento. Para el momento del próximo intento de renderizado, las props podrían ser diferentes. Es por eso que este método es «inseguro». El código que debe ejecutarse solo para actualizaciones confirmadas (como restablecer una suscripción) debe ir en componentDidUpdate.

  • UNSAFE_componentWillReceiveProps no significa que el componente haya recibido props diferentes a las de la última vez. Debes comparar nextProps y this.props por ti mismo para verificar si algo ha cambiado.

  • React no llama a UNSAFE_componentWillReceiveProps con props iniciales durante el montaje. Solo llama a este método si alguna de las props del componente se va a actualizar. Por ejemplo, llamar a setState generalmente no activa UNSAFE_componentWillReceiveProps dentro del mismo componente.

Nota

Llamar a setState dentro de UNSAFE_componentWillReceiveProps en un componente de clase para «ajustar» el estado es equivalente a llamar a la función set de useState durante el renderizado en un componente de función.


UNSAFE_componentWillUpdate(nextProps, nextState)

Si defines UNSAFE_componentWillUpdate, React lo llamará antes de renderizar con las nuevas props o estado. Solo existe por razones históricas y no debe usarse en ningún código nuevo. En su lugar, usa una de las alternativas siguientes:

  • Si necesitas realizar un efecto secundario (por ejemplo, recuperar datos, ejecutar una animación o reinicializar una suscripción) en respuesta a cambios de prop o estado, mueve esa lógica a componentDidUpdate en su lugar.
  • Si necesitas leer alguna información del DOM (por ejemplo, para guardar la posición actual de desplazamiento) para usarla en componentDidUpdate más tarde, léela dentro de getSnapshotBeforeUpdate en su lugar.

Ver ejemplos de migración de ciclos de vida inseguros.

Parámetros

  • nextProps: Las próximas props con las que el componente está a punto de renderizarse. Compara nextProps con this.props para determinar qué ha cambiado.
  • nextState: El próximo estado con el que el componente está a punto de renderizarse. Compara nextState con this.state para determinar qué ha cambiado.

Retorna

UNSAFE_componentWillUpdate no debería devolver nada.

Precauciones

  • UNSAFE_componentWillUpdate no se llamará si shouldComponentUpdate está definido y devuelve false.

  • UNSAFE_componentWillUpdate no se llamará si el componente implementa static getDerivedStateFromProps o getSnapshotBeforeUpdate.

  • No es compatible llamar a setState (o cualquier método que lleve a que se llame a setState, como despachar una acción de Redux) durante componentWillUpdate.

  • A pesar de su nombre, UNSAFE_componentWillUpdate no garantiza que el componente se actualizará si su aplicación utiliza características modernas de React como Suspense. Si se suspende un intento de renderizado (por ejemplo, porque el código para algún componente hijo aún no se ha cargado), React descarta el árbol en progreso e intenta construir el componente desde cero durante el próximo intento. Para el momento del próximo intento de renderizado, las props y el estado pueden ser diferentes. Es por eso que este método es «peligroso». El código que solo debe ejecutarse para actualizaciones comprometidas (como restablecer una suscripción) debe ir en componentDidUpdate.

  • UNSAFE_componentWillUpdate no significa que el componente haya recibido props o estado diferentes que la última vez. Necesitas comparar nextProps con this.props y nextState con this.state por ti mismo para verificar si algo ha cambiado.

  • React no llama a UNSAFE_componentWillUpdate con las props y el estado iniciales durante el montaje.

Nota

No hay un equivalente directo a UNSAFE_componentWillUpdate en componentes de función.


static childContextTypes

Obsoleto

Esta API será eliminada en una futura versión importante de React. En su lugar, usa static contextType.

Te permite especificar qué contexto legado es proporcionado por este componente.


static contextTypes

Obsoleto

Esta API será eliminada en una versión mayor futura de React. Use static contextType en su lugar.

Te permite especificar qué contexto heredado es consumido por este componente.


static contextType

Si deseas leer this.context desde tu componente de clase, debes especificar qué contexto debe leer. El contexto que especifiques como static contextType debe ser un valor creado previamente por createContext.

class Button extends Component {
static contextType = ThemeContext;

render() {
const theme = this.context;
const className = 'button-' + theme;
return (
<button className={className}>
{this.props.children}
</button>
);
}
}

Nota

Leer this.context en componentes de clase es equivalente a useContext en componentes de función.

Mira cómo migrar.


static defaultProps

Puedes definir static defaultProps para establecer las props predeterminadas para la clase. Se utilizarán para props undefined y faltantes, pero no para props null.

Por ejemplo, así es como defines que la prop color debe tener como valor predeterminado 'blue':

class Button extends Component {
static defaultProps = {
color: 'blue'
};

render() {
return <button className={this.props.color}>click me</button>;
}
}

Si la propiedad color no se proporciona o es undefined, se establecerá por defecto en 'blue':

<>
{/* this.props.color is "blue" */}
<Button />

{/* this.props.color is "blue" */}
<Button color={undefined} />

{/* this.props.color is null */}
<Button color={null} />

{/* this.props.color is "red" */}
<Button color="red" />
</>

Nota

Definir defaultProps en componentes de clase es similar a usar valores predeterminados en componentes de función.


static getDerivedStateFromError(error)

Si defines static getDerivedStateFromError, React lo llamará cuando un componente hijo (incluyendo componentes hijos distantes) arroje un error durante el rendering. Esto te permite mostrar un mensaje de error en lugar de limpiar la interfaz de usuario.

Por lo general, se utiliza junto con componentDidCatch, que te permite enviar el informe de errores a algún servicio de análisis. Un componente con estos métodos se llama una línea de error.

Mira un ejemplo.

Parámetros

  • error: El error que se produjo. En la práctica, generalmente será una instancia de Error, pero esto no está garantizado porque JavaScript permite arrojar cualquier valor, incluyendo cadenas o incluso null.

Retorna

static getDerivedStateFromError debería devolver el estado que indica al componente que muestre el mensaje de error.

Precauciones

  • static getDerivedStateFromError debe ser una función pura. Si deseas realizar un efecto secundario (por ejemplo, llamar a un servicio de análisis), también debes implementar componentDidCatch.

Nota

Todavía no existe un equivalente directo de static getDerivedStateFromError en componentes de función. Si desea evitar crear componentes de clase, escriba un solo componente ErrorBoundary como se muestra arriba y úselo en toda su aplicación. Alternativamente, utilice el paquete react-error-boundary que lo hace.


static getDerivedStateFromProps(props, state)

Si defines static getDerivedStateFromProps, React lo llamará justo antes de llamar a render, tanto en el montaje inicial como en actualizaciones posteriores. Debería devolver un objeto para actualizar el estado, o null para no actualizar nada.

Este método existe para casos de uso raros donde el estado depende de los cambios en las propiedades con el tiempo. Por ejemplo, este componente Form restablece el estado email cuando cambia la propiedad userID:

class Form extends Component {
state = {
email: this.props.defaultEmail,
prevUserID: this.props.userID
};

static getDerivedStateFromProps(props, state) {
// Any time the current user changes,
// Reset any parts of state that are tied to that user.
// In this simple example, that's just the email.
if (props.userID !== state.prevUserID) {
return {
prevUserID: props.userID,
email: props.defaultEmail
};
}
return null;
}

// ...
}

Ten en cuenta que este patrón requiere que mantengas un valor anterior de la propiedad (como userID) en el estado (como prevUserID).

Atención

Derivar el estado conduce a un código verboso y hace que tus componentes sean difíciles de entender. Asegúrate de estar familiarizado con alternativas más simples:

Parámetros

  • props: Las próximas props que el componente está a punto de renderizar.
  • state: El próximo estado que el componente está a punto de renderizar.

Retorna

static getDerivedStateFromProps devuelve un objeto para actualizar el estado, o null para no actualizar nada.

Precauciones

  • Este método se ejecuta en cada renderización, independientemente de la causa. Esto es diferente de UNSAFE_componentWillReceiveProps, que solo se ejecuta cuando el padre causa una re-renderización y no como resultado de un setState local.
  • Este método no tiene acceso a la instancia del componente. Si lo desea, puede reutilizar algún código entre static getDerivedStateFromProps y otros métodos de clase extrayendo funciones puras de las props y el estado del componente fuera de la definición de la clase.

Nota

Implementar static getDerivedStateFromProps en un componente de clase es equivalente a llamar a la función set de useState durante el renderizado en un componente de función.


Uso

Definiendo un componente de clase

Para definir un componente React como una clase, extiende la clase integrada Component y define un método render:.

import { Component } from 'react';

class Greeting extends Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}

React llamará a tu método render cada vez que necesite determinar qué mostrar en la pantalla. Por lo general, devolverás algo de JSX. Tu método render debe ser una función pura: solo debe calcular el JSX.

De manera similar a los componentes de función, un componente de clase puede recibir información mediante props de su componente padre. Sin embargo, la sintaxis para leer los props es diferente. Por ejemplo, si el componente padre renderiza <Greeting name="Taylor" />, entonces puedes leer el prop name desde this.props, como this.props.name:

import { Component } from 'react';

class Greeting extends Component {
  render() {
    return <h1>Hello, {this.props.name}!</h1>;
  }
}

export default function App() {
  return (
    <>
      <Greeting name="Sara" />
      <Greeting name="Cahal" />
      <Greeting name="Edite" />
    </>
  );
}

Ten en cuenta que los Hooks (funciones que comienzan con use, como useState) no son compatibles dentro de componentes de clase.

Atención

Recomendamos definir los componentes como funciones en lugar de clases. Mira cómo migrar.


Añadiendo estado a un componente de clase

Para agregar estado a una clase, se debe asignar un objeto a una propiedad llamada state. Para actualizar el estado, se debe llamar a this.setState.

import { Component } from 'react';

export default class Counter extends Component {
  state = {
    name: 'Taylor',
    age: 42,
  };

  handleNameChange = (e) => {
    this.setState({
      name: e.target.value
    });
  }

  handleAgeChange = () => {
    this.setState({
      age: this.state.age + 1 
    });
  };

  render() {
    return (
      <>
        <input
          value={this.state.name}
          onChange={this.handleNameChange}
        />
        <button onClick={this.handleAgeChange}>
          Incrementar edad
        </button>
        <p>Hola, {this.state.name}. Tienes {this.state.age} años.</p>
      </>
    );
  }
}

Atención

Recomendamos definir los componentes como funciones en lugar de clases. Mira cómo hacer la transición.


Añadiendo métodos de ciclo de vida a un componente de clase

Hay algunos métodos especiales que puedes definir en tu clase.

Si defines el método componentDidMount, React lo llamará cuando tu componente se agregue (monte) por primera vez en la pantalla. React llamará a componentDidUpdate después de que tu componente se vuelva a renderizar debido a cambios en las props o el estado. React llamará a componentWillUnmount después de que tu componente se haya eliminado (desmontado) de la pantalla.

Si implementas componentDidMount, generalmente necesitarás implementar los tres ciclos de vida para evitar errores. Por ejemplo, si componentDidMount lee algún estado o props, también debes implementar componentDidUpdate para manejar sus cambios, y componentWillUnmount para limpiar lo que componentDidMount estaba haciendo.

Por ejemplo, este componente ChatRoom mantiene una conexión de chat sincronizada con las props y el estado:

import { Component } from 'react';
import { createConnection } from './chat.js';

export default class ChatRoom extends Component {
  state = {
    serverUrl: 'https://localhost:1234'
  };

  componentDidMount() {
    this.setupConnection();
  }

  componentDidUpdate(prevProps, prevState) {
    if (
      this.props.roomId !== prevProps.roomId ||
      this.state.serverUrl !== prevState.serverUrl
    ) {
      this.destroyConnection();
      this.setupConnection();
    }
  }

  componentWillUnmount() {
    this.destroyConnection();
  }

  setupConnection() {
    this.connection = createConnection(
      this.state.serverUrl,
      this.props.roomId
    );
    this.connection.connect();    
  }

  destroyConnection() {
    this.connection.disconnect();
    this.connection = null;
  }

  render() {
    return (
      <>
        <label>
          Server URL:{' '}
          <input
            value={this.state.serverUrl}
            onChange={e => {
              this.setState({
                serverUrl: e.target.value
              });
            }}
          />
        </label>
        <h1>Bienvenido al chat {this.props.roomId}!</h1>
      </>
    );
  }
}

Nota que en desarrollo, cuando Strict Mode está activado, React llamará a componentDidMount, luego llamará inmediatamente a componentWillUnmount, y luego llamará a componentDidMount nuevamente. Esto te ayuda a notar si olvidaste implementar componentWillUnmount o si su lógica no refleja completamente lo que hace componentDidMount.

Atención

Recomendamos definir los componentes como funciones en lugar de clases. Mira cómo migrar.


Capturando errores de renderizado con un error boundary

Por defecto, si tu aplicación lanza un error durante el renderizado, React eliminará su interfaz de usuario de la pantalla. Para evitar esto, puedes envolver una parte de tu interfaz de usuario en un error boundary. Un error boundary es un componente especial que te permite mostrar alguna interfaz de usuario alternativa en lugar de la que falló, por ejemplo, un mensaje de error.

Para implementar un componente de error boundary, debes proporcionar static getDerivedStateFromError que te permite actualizar el estado en respuesta a un error y mostrar un mensaje de error al usuario. También puedes implementar opcionalmente componentDidCatch para agregar algo de lógica adicional, por ejemplo, para registrar el error en un servicio de análisis.

class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}

static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}

componentDidCatch(error, info) {
// Example "componentStack":
// in ComponentThatThrows (created by App)
// in ErrorBoundary (created by App)
// in div (created by App)
// in App
logErrorToMyService(error, info.componentStack);
}

render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return this.props.fallback;
}

return this.props.children;
}
}

Luego, puedes envolver una parte de tu árbol de componentes con él:

<ErrorBoundary fallback={<p>Something went wrong</p>}>
<Profile />
</ErrorBoundary>

Si Profile o su componente hijo arroja un error, ErrorBoundary «capturará» ese error, mostrará una IU de respaldo con el mensaje de error que ha proporcionado y enviará un informe de error de producción a su servicio de informes de errores.

No es necesario envolver cada componente en un error boundary por separado. Al considerar la granularidad de los error boundaries, considere dónde tiene sentido mostrar un mensaje de error. Por ejemplo, en una aplicación de mensajería, tiene sentido colocar un error boundary alrededor de la lista de conversaciones. También tiene sentido colocar uno alrededor de cada mensaje individual. Sin embargo, no tendría sentido colocar un límite alrededor de cada avatar.

Nota

Actualmente, no hay forma de escribir un error boundary como un componente de función. Sin embargo, no tienes que escribir la clase del error boundary tú mismo. Por ejemplo, puedes usar react-error-boundary en su lugar.


Alternativas

Migrando un componente simple de clase a función

Por lo general, definirás los componentes como funciones.

Por ejemplo, supongamos que estás convirtiendo este componente de clase Greeting en una función:

import { Component } from 'react';

class Greeting extends Component {
  render() {
    return <h1>Hola, {this.props.name}!</h1>;
  }
}

export default function App() {
  return (
    <>
      <Greeting name="Sara" />
      <Greeting name="Cahal" />
      <Greeting name="Edite" />
    </>
  );
}

Defina una función llamada Greeting. Aquí es donde moverá el cuerpo de su función render.

function Greeting() {
// ... move the code from the render method here ...
}

En lugar de this.props.name, define la prop name usando la sintaxis de desestructuración y lee directamente de ella:

function Greeting({ name }) {
return <h1>Hola, {name}!</h1>;
}

Aquí tienes un ejemplo completo:

function Greeting({ name }) {
  return <h1>Hello, {name}!</h1>;
}

export default function App() {
  return (
    <>
      <Greeting name="Sara" />
      <Greeting name="Cahal" />
      <Greeting name="Edite" />
    </>
  );
}


Migrando un componente con estado de clase a funcion

Supongamos que estás convirtiendo este componente de clase Counter en una función:

import { Component } from 'react';

export default class Counter extends Component {
  state = {
    name: 'Taylor',
    age: 42,
  };

  handleNameChange = (e) => {
    this.setState({
      name: e.target.value
    });
  }

  handleAgeChange = (e) => {
    this.setState({
      age: this.state.age + 1 
    });
  };

  render() {
    return (
      <>
        <input
          value={this.state.name}
          onChange={this.handleNameChange}
        />
        <button onClick={this.handleAgeChange}>
          Incrementar edad
        </button>
        <p>Hola, {this.state.name}. Tienes {this.state.age} años.</p>
      </>
    );
  }
}

Empieza declarando una función con las variables de estado necesarias:

import { useState } from 'react';

function Counter() {
const [name, setName] = useState('Taylor');
const [age, setAge] = useState(42);
// ...

A continuación, convierte los manejadores de eventos:

function Counter() {
const [name, setName] = useState('Taylor');
const [age, setAge] = useState(42);

function handleNameChange(e) {
setName(e.target.value);
}

function handleAgeChange() {
setAge(age + 1);
}
// ...

Finalmente, reemplaza todas las referencias que comienzan con this con las variables y funciones que definiste en tu componente. Por ejemplo, reemplaza this.state.age con age, y reemplaza this.handleNameChange con handleNameChange.

Aquí tienes el componente completamente convertido:

import { useState } from 'react';

export default function Counter() {
  const [name, setName] = useState('Taylor');
  const [age, setAge] = useState(42);

  function handleNameChange(e) {
    setName(e.target.value);
  }

  function handleAgeChange() {
    setAge(age + 1);
  }

  return (
    <>
      <input
        value={name}
        onChange={handleNameChange}
      />
      <button onClick={handleAgeChange}>
        Incrementar edad
      </button>
      <p>Hola, {name}. Tienes {age} años.</p>
    </>
  )
}


Migrando un componente con métodos de ciclo de vida de clase a funcion

Supongamos que estás convirtiendo este componente de clase ChatRoom con métodos del ciclo de vida a una función:

import { Component } from 'react';
import { createConnection } from './chat.js';

export default class ChatRoom extends Component {
  state = {
    serverUrl: 'https://localhost:1234'
  };

  componentDidMount() {
    this.setupConnection();
  }

  componentDidUpdate(prevProps, prevState) {
    if (
      this.props.roomId !== prevProps.roomId ||
      this.state.serverUrl !== prevState.serverUrl
    ) {
      this.destroyConnection();
      this.setupConnection();
    }
  }

  componentWillUnmount() {
    this.destroyConnection();
  }

  setupConnection() {
    this.connection = createConnection(
      this.state.serverUrl,
      this.props.roomId
    );
    this.connection.connect();    
  }

  destroyConnection() {
    this.connection.disconnect();
    this.connection = null;
  }

  render() {
    return (
      <>
        <label>
          Server URL:{' '}
          <input
            value={this.state.serverUrl}
            onChange={e => {
              this.setState({
                serverUrl: e.target.value
              });
            }}
          />
        </label>
        <h1>Bienvenido al chat {this.props.roomId}!</h1>
      </>
    );
  }
}

Primero, verifica que tu método componentWillUnmount haga lo contrario de componentDidMount. En el ejemplo anterior, eso es cierto: desconecta la conexión que componentDidMount establece. Si falta tal lógica, agregala primero.

A continuación, verifica que tu método componentDidUpdate maneje los cambios en todas las props y el estado que estás usando en componentDidMount. En el ejemplo anterior, componentDidMount llama a setupConnection que lee this.state.serverUrl y this.props.roomId. Es por eso que componentDidUpdate verifica si this.state.serverUrl y this.props.roomId han cambiado, y restablece la conexión si lo hicieron. Si falta la lógica de componentDidUpdate o no maneja los cambios en todas las props y el estado relevantes, corrígelo primero.

En el ejemplo anterior, la lógica dentro de los métodos de ciclo de vida conecta el componente a un sistema fuera de React (un servidor de chat). Para conectar un componente a un sistema externo, describe esta lógica como un solo Effect:

import { useState, useEffect } from 'react';

function ChatRoom({ roomId }) {
const [serverUrl, setServerUrl] = useState('https://localhost:1234');

useEffect(() => {
const connection = createConnection(serverUrl, roomId);
connection.connect();
return () => {
connection.disconnect();
};
}, [serverUrl, roomId]);

// ...
}

Esta llamada a useEffect es equivalente a la lógica en los métodos del ciclo de vida mencionados anteriormente. Si sus métodos del ciclo de vida realizan varias cosas no relacionadas, divídalos en varios efectos independientes. Aquí hay un ejemplo completo con el que puede trabajar:

import { useState, useEffect } from 'react';
import { createConnection } from './chat.js';

export default function ChatRoom({ roomId }) {
  const [serverUrl, setServerUrl] = useState('https://localhost:1234');

  useEffect(() => {
    const connection = createConnection(serverUrl, roomId);
    connection.connect();
    return () => {
      connection.disconnect();
    };
  }, [roomId, serverUrl]);

  return (
    <>
      <label>
        Server URL:{' '}
        <input
          value={serverUrl}
          onChange={e => setServerUrl(e.target.value)}
        />
      </label>
      <h1>Bienvenido al chat {roomId}!</h1>
    </>
  );
}

Nota

Si tu componente no se sincroniza con ningún sistema externo, es posible que no necesites un Effect.


Migrando un componente con contexto de clase a funcion

En este ejemplo, los componentes de clase Panel y Button leen el contexto desde this.context:

import { createContext, Component } from 'react';

const ThemeContext = createContext(null);

class Panel extends Component {
  static contextType = ThemeContext;

  render() {
    const theme = this.context;
    const className = 'panel-' + theme;
    return (
      <section className={className}>
        <h1>{this.props.title}</h1>
        {this.props.children}
      </section>
    );    
  }
}

class Button extends Component {
  static contextType = ThemeContext;

  render() {
    const theme = this.context;
    const className = 'button-' + theme;
    return (
      <button className={className}>
        {this.props.children}
      </button>
    );
  }
}

function Form() {
  return (
    <Panel title="Bienvenido">
      <Button>Sign up</Button>
      <Button>Log in</Button>
    </Panel>
  );
}

export default function MyApp() {
  return (
    <ThemeContext.Provider value="dark">
      <Form />
    </ThemeContext.Provider>
  )
}

Cuando los conviertas a componentes de función, reemplaza this.context con llamadas a useContext:

import { createContext, useContext } from 'react';

const ThemeContext = createContext(null);

function Panel({ title, children }) {
  const theme = useContext(ThemeContext);
  const className = 'panel-' + theme;
  return (
    <section className={className}>
      <h1>{title}</h1>
      {children}
    </section>
  )
}

function Button({ children }) {
  const theme = useContext(ThemeContext);
  const className = 'button-' + theme;
  return (
    <button className={className}>
      {children}
    </button>
  );
}

function Form() {
  return (
    <Panel title="Bienvenido">
      <Button>Sign up</Button>
      <Button>Log in</Button>
    </Panel>
  );
}

export default function MyApp() {
  return (
    <ThemeContext.Provider value="dark">
      <Form />
    </ThemeContext.Provider>
  )
}