Un componente de clase es una clase de JavaScript que extiende React.Component y devuelve JSX desde un método render(). Lee las props de this.props, guarda el estado en this.state y lo actualiza con this.setState(). Los componentes de función con hooks los reemplazaron para el código nuevo, pero las clases siguen siendo totalmente compatibles, aparecen en mucho código antiguo y son la única forma de escribir un error boundary.
Cada contador guarda su propio estado. Agrega un tercer <Counter label="Plums" /> y también empieza en 0.
La anatomía de un componente de clase
import { Component } from 'react';
class Welcome extends Component {
static defaultProps = { name: 'stranger' };
constructor(props) {
super(props); // required before using this
this.state = { visits: 1 };
}
render() {
return <h1>Hello, {this.props.name}. Visit #{this.state.visits}</h1>;
}
}
- La clase extiende
Component(oReact.Componentconimport React from 'react'). render()es obligatorio. Debe ser puro, como el cuerpo de un componente de función: leethis.propsythis.state, devuelve JSX.this.propscontiene las props. Son de solo lectura.- El estado se puede definir en un
constructor(llama primero asuper(props)) o, más habitual hoy, como campo de clase:state = { visits: 1 };. static defaultPropssigue funcionando para las clases en React 19 (solo se eliminó para los componentes de función).
this.setState combina, y puede recibir una función de actualización
setState hace dos cosas de forma distinta al setter de useState. Combina el objeto que pasas con el estado actual, así que solo actualizas las claves que nombras. Y, como toda actualización de estado de React, no se aplica de inmediato, así que usa la forma de actualización cuando el siguiente valor depende del anterior.
"+3 with objects" suma uno, porque las tres llamadas leen el mismo this.state.likes. "+3 with updaters" suma tres. "Move to Paris" conserva name y likes (la combinación) pero pierde zip, porque la combinación solo llega a un nivel de profundidad. Escribe address: { ...this.state.address, city: 'Paris' } para conservarlo. El segundo argumento opcional de setState se ejecuta después de la actualización, y la consola muestra ahí la nueva dirección.
Enlazar manejadores de eventos
Un método pasado como onClick={this.handleClick} se llama más tarde como una función normal, sin su objeto, así que this dentro de él es undefined.
El primer botón registra un TypeError sobre leer setState de undefined. El segundo funciona, porque una función flecha en un campo de clase captura this cuando se crea la instancia. La solución antigua, todavía común en código heredado, enlaza en el constructor:
constructor(props) {
super(props);
this.state = { on: false };
this.handleClick = this.handleClick.bind(this);
}
Una flecha en línea, onClick={() => this.handleClick()}, también funciona.
Métodos de ciclo de vida
Las clases reaccionan al montaje, la actualización y el desmontaje mediante métodos con nombres fijos. Los que más verás:
componentDidMount(): cuando el primer renderizado está en el DOM. Inicia temporizadores, suscripciones, peticiones.componentDidUpdate(prevProps, prevState): después de cada actualización. Compara con los valores anteriores antes de hacer trabajo, o entrarás en un bucle.componentWillUnmount(): antes de quitarse. Deshace lo que iniciócomponentDidMount.shouldComponentUpdate(nextProps, nextState): devuelvefalsepara saltarte un renderizado.
La página de ciclo de vida de componentes tiene la lista completa, el orden en que se ejecutan y un componente que registra cada uno.
Convertir una clase en un componente de función
Aquí tienes una clase que usa los tres métodos de ciclo de vida habituales. Avanza cada segundo, registra cuando cambia su prop label y detiene su temporizador cuando se quita.
Y el mismo componente como función. Cada método de ciclo de vida pasa a formar parte de un efecto, y la configuración y la limpieza relacionadas quedan juntas en lugar de en dos métodos.
Ambos temporizadores cuentan igual y registran en cada cambio de etiqueta. La versión de función además registra una vez al montar, porque un efecto también se ejecuta después del primer renderizado. Los pasos para cualquier conversión:
this.props.xpasa a ser una prop desestructurada,{ x }.- Cada clave de
this.statepasa a ser su propiouseState. Recuerda que el setter reemplaza en lugar de combinar. - Los métodos pasan a ser funciones normales dentro del componente. No hace falta enlazarlos.
componentDidMount,componentDidUpdateycomponentWillUnmountpasan a ser llamadas auseEffect, agrupadas por lo que hacen y no por cuándo se ejecutan.createRefpasa a seruseRef, ystatic contextTypeconthis.contextpasa a seruseContextouse.
Deja los error boundaries como clases; no tienen equivalente en funciones.
PureComponent
Un componente de clase normal renderiza cada vez que lo hace su padre. PureComponent compara primero las props y el estado nuevos con los anteriores, a un nivel de profundidad, y se salta el renderizado cuando nada cambió. Es la contraparte de clase de React.memo.
Haz clic en el botón: solo se registra PlainLabel rendered, porque PureLabel ve el mismo text. Pasa text={'hello ' + clicks} a ambos y los dos renderizan en cada clic.
La comparación es superficial, así que una prop que es un objeto o una función nueva en cada renderizado del padre (style={{ color: 'red' }}, onClick={() => ...}) la anula. Es la misma trampa que con React.memo.
Lo que React 19 quitó de las clases
Si mantienes código de clases antiguo, algunos patrones ya no funcionan en React 19:
- String refs (
ref="input"conthis.refs.input). UsacreateRef()o una ref callback. - Contexto heredado (
contextTypes,childContextTypes,getChildContext). UsacreateContextconstatic contextType. propTypesse ignoran. Usa TypeScript o tus propias comprobaciones.findDOMNodedesapareció. Pon una ref en el elemento del DOM.
Los viejos métodos componentWillMount, componentWillReceiveProps y componentWillUpdate también son heredados. Siguen ejecutándose, tanto con los nombres antiguos como con los nombres UNSAFE_ (UNSAFE_componentWillMount y demás), pero están obsoletos y StrictMode avisa sobre ellos; mueve su código a componentDidMount, componentDidUpdate o getDerivedStateFromProps.
Preguntas frecuentes
¿Los componentes de clase están obsoletos en React?
No. Siguen siendo compatibles en React 19 y seguirán funcionando, pero la documentación de React recomienda componentes de función con hooks para el código nuevo. Todavía necesitas una clase para los error boundaries.
¿Cuál es la diferencia entre componentes de clase y de función?
Un componente de clase guarda el estado en this.state, lo actualiza con this.setState y reacciona al ciclo de vida mediante métodos con nombre. Un componente de función usa hooks (useState, useEffect) para lo mismo, no necesita this y es más corto.
¿setState actualiza el estado de inmediato?
No. this.setState programa una actualización y React renderiza después, así que this.state sigue teniendo el valor viejo justo después de la llamada. Pasa una función, this.setState((state) => ...), cuando el nuevo valor depende del anterior, o lee el resultado en el callback del segundo argumento o en componentDidUpdate.
¿Por qué this es undefined en mi manejador de eventos?
Un método de clase pasado como onClick={this.handleClick} se llama sin su objeto, así que this es undefined. Define el manejador como una función flecha en un campo de clase (handleClick = () => { ... }) o enlázalo en el constructor.
¿Qué es PureComponent?
Un Component que se salta el renderizado cuando sus props y su estado son superficialmente iguales a los anteriores. Es la versión de clase de React.memo.