Menu

Componentes de classe no React: estado e ciclo de vida

Um componente de classe é uma classe JavaScript que estende React.Component e retorna JSX de um método render. Aprenda this.props, this.state e setState, o bind de event handlers, os métodos de ciclo de vida, o PureComponent e como converter uma classe em um componente de função.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

Um componente de classe é uma classe JavaScript que estende React.Component e retorna JSX de um método render(). Ele lê as props de this.props, guarda o estado em this.state e o atualiza com this.setState(). Componentes de função com hooks os substituíram em código novo, mas as classes continuam totalmente suportadas, aparecem em muitos códigos mais antigos e são a única forma de escrever um error boundary.

Cada contador guarda o próprio estado. Adicione um terceiro <Counter label="Plums" /> e ele também começa em 0.

A anatomia de um componente de classe

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>;
    }
}
  • A classe estende Component (ou React.Component com import React from 'react').
  • render() é obrigatório. Ele precisa ser puro, como o corpo de um componente de função: ler this.props e this.state e retornar JSX.
  • this.props guarda as props. Elas são somente leitura.
  • O estado pode ser definido em um constructor (chame super(props) antes) ou, o mais comum hoje, como class field: state = { visits: 1 };.
  • static defaultProps continua funcionando para classes no React 19 (ele só foi removido para componentes de função).

this.setState mescla e aceita uma função de atualização

O setState faz duas coisas de um jeito diferente do setter do useState. Ele mescla o objeto que você passa com o estado atual, então você atualiza só as chaves que nomear. E, como toda atualização de estado no React, ele não é aplicado na hora, então use a forma com função de atualização quando o próximo valor depender do anterior.

"+3 with objects" soma um, porque as três chamadas leem o mesmo this.state.likes. "+3 with updaters" soma três. "Move to Paris" mantém name e likes (a mesclagem), mas perde zip, porque a mesclagem só tem um nível de profundidade. Escreva address: { ...this.state.address, city: 'Paris' } para mantê-lo. O segundo argumento opcional do setState executa depois da atualização, e o console mostra o novo endereço ali.

Fazendo o bind dos event handlers

Um método passado como onClick={this.handleClick} é chamado depois como uma função comum, sem o objeto, então this dentro dele é undefined.

O primeiro botão registra um TypeError sobre ler setState de undefined. O segundo funciona, porque uma arrow function em um class field captura o this quando a instância é criada. A correção mais antiga, ainda comum em código legado, faz o bind no construtor:

constructor(props) {
    super(props);
    this.state = { on: false };
    this.handleClick = this.handleClick.bind(this);
}

Uma arrow inline, onClick={() => this.handleClick()}, também funciona.

Métodos de ciclo de vida

As classes reagem à montagem, à atualização e à desmontagem por meio de métodos com nomes fixos. Os que você mais vai ver:

  • componentDidMount(): depois que a primeira renderização está no DOM. Inicie timers, assinaturas, requisições.
  • componentDidUpdate(prevProps, prevState): depois de cada atualização. Compare com os valores anteriores antes de fazer algo, ou você entra em loop.
  • componentWillUnmount(): antes da remoção. Desfaça o que o componentDidMount iniciou.
  • shouldComponentUpdate(nextProps, nextState): retorne false para pular uma renderização.

A página sobre o ciclo de vida dos componentes tem a lista completa, a ordem em que executam e um componente que registra cada um deles.

Convertendo uma classe em um componente de função

Aqui está uma classe que usa os três métodos de ciclo de vida mais comuns. Ela conta a cada segundo, registra quando a prop label muda e para o timer quando é removida.

E o mesmo componente como função. Cada método de ciclo de vida vira parte de um efeito, e o setup e a limpeza relacionados ficam lado a lado em vez de em dois métodos.

Os dois timers contam do mesmo jeito e registram a cada mudança de rótulo. A versão em função também registra uma vez na montagem, já que um efeito também executa depois da primeira renderização. Os passos de qualquer conversão:

  1. this.props.x vira uma prop desestruturada, { x }.
  2. Cada chave de this.state vira o próprio useState. Lembre que o setter substitui em vez de mesclar.
  3. Os métodos viram funções comuns dentro do componente. Sem necessidade de bind.
  4. componentDidMount, componentDidUpdate e componentWillUnmount viram chamadas de useEffect, agrupadas pelo que fazem e não por quando executam.
  5. createRef vira useRef, e static contextType com this.context vira useContext ou use.

Deixe os error boundaries como classes; eles não têm equivalente em função.

PureComponent

Um componente de classe normal renderiza toda vez que o pai renderiza. O PureComponent primeiro compara as novas props e o novo estado com os anteriores, em um nível de profundidade, e pula a renderização quando nada mudou. Ele é o equivalente em classe do React.memo.

Clique no botão: só PlainLabel rendered é registrado, porque PureLabel vê o mesmo text. Passe text={'hello ' + clicks} para os dois e os dois renderizam a cada clique.

A comparação é superficial, então uma prop que é um novo objeto ou uma nova função a cada renderização do pai (style={{ color: 'red' }}, onClick={() => ...}) a anula. É a mesma armadilha do React.memo.

O que o React 19 removeu das classes

Se você mantém código antigo com classes, alguns padrões não funcionam mais no React 19:

  • String refs (ref="input" com this.refs.input). Use createRef() ou uma ref callback.
  • Context legado (contextTypes, childContextTypes, getChildContext). Use createContext com static contextType.
  • propTypes são ignorados. Use TypeScript ou suas próprias verificações.
  • findDOMNode não existe mais. Coloque uma ref no elemento do DOM.

Os antigos métodos componentWillMount, componentWillReceiveProps e componentWillUpdate também são legados. Eles ainda executam, tanto com os nomes antigos quanto com os nomes UNSAFE_ (UNSAFE_componentWillMount e assim por diante), mas estão descontinuados e o StrictMode avisa sobre eles; leve o código deles para componentDidMount, componentDidUpdate ou getDerivedStateFromProps.

Perguntas frequentes

Os componentes de classe foram descontinuados no React?

Não. Eles continuam suportados no React 19 e vão continuar funcionando, mas a documentação do React recomenda componentes de função com hooks para código novo. Você ainda precisa de uma classe para error boundaries.

Qual é a diferença entre componentes de classe e de função?

Um componente de classe guarda o estado em this.state, o atualiza com this.setState e reage ao ciclo de vida por meio de métodos com nome. Um componente de função usa hooks (useState, useEffect) para as mesmas tarefas, não precisa de this e é mais curto.

O setState atualiza o estado na hora?

Não. this.setState agenda uma atualização e o React renderiza depois, então this.state ainda tem o valor antigo logo depois da chamada. Passe uma função, this.setState((state) => ...), quando o novo valor depender do antigo, ou leia o resultado na callback do segundo argumento ou no componentDidUpdate.

Por que this é undefined no meu event handler?

Um método da classe passado como onClick={this.handleClick} é chamado sem o objeto, então this é undefined. Defina o handler como uma arrow function em um class field (handleClick = () => { ... }) ou faça o bind no construtor.

O que é o PureComponent?

Um Component que pula a renderização quando as props e o estado são superficialmente iguais aos anteriores. É a versão de classe do React.memo.

Ilustração das linguagens de programação do Coddy

Aprenda a programar com o Coddy

COMEÇAR