Component
é a classe base para os componentes React definidos como classes JavaScript. Componentes de classe ainda são suportados pelo React, mas não recomendamos usá-los em código novo.
class Greeting extends Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
- Referência
Component
context
props
state
constructor(props)
componentDidCatch(error, info)
componentDidMount()
componentDidUpdate(prevProps, prevState, snapshot?)
componentWillMount()
componentWillReceiveProps(nextProps)
componentWillUpdate(nextProps, nextState)
componentWillUnmount()
forceUpdate(callback?)
getSnapshotBeforeUpdate(prevProps, prevState)
render()
setState(nextState, callback?)
shouldComponentUpdate(nextProps, nextState, nextContext)
UNSAFE_componentWillMount()
UNSAFE_componentWillReceiveProps(nextProps, nextContext)
UNSAFE_componentWillUpdate(nextProps, nextState)
static contextType
static defaultProps
static getDerivedStateFromError(error)
static getDerivedStateFromProps(props, state)
- Uso
- Alternativas
Referência
Component
Para definir um componente React como uma classe, estenda a classe Component
integrada e defina um método render
:
import { Component } from 'react';
class Greeting extends Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
Somente o método render
é obrigatório, outros métodos são opcionais.
context
O contexto de um componente de classe está disponível como this.context
. Ele só estará disponível se você especificar qual contexto deseja receber usando static contextType
.
Um componente de classe só pode ler um contexto por 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>
);
}
}
props
As props passadas para um componente de classe estão disponíveis como this.props
.
class Greeting extends Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
<Greeting name="Taylor" />
state
O estado de um componente de classe está disponível como this.state
. O campo state
deve ser um objeto. Não mute o estado diretamente. Se você deseja alterar o estado, chame setState
com o novo estado.
class Counter extends Component {
state = {
age: 42,
};
handleAgeChange = () => {
this.setState({
age: this.state.age + 1
});
};
render() {
return (
<>
<button onClick={this.handleAgeChange}>
Increment age
</button>
<p>You are {this.state.age}.</p>
</>
);
}
}
constructor(props)
O constructor é executado antes que seu componente de classe seja montado (adicionado à tela). Normalmente, um construtor é usado apenas para dois propósitos no React. Ele permite que você declare o state e faça o bind
de seus métodos de classe para a instância da classe:
class Counter extends Component {
constructor(props) {
super(props);
this.state = { counter: 0 };
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
// ...
}
Se você usar a sintaxe moderna do JavaScript, os construtores raramente são necessários. Em vez disso, você pode reescrever o código acima usando a sintaxe de campo de classe pública, que é suportada tanto por navegadores modernos quanto por ferramentas como Babel:
class Counter extends Component {
state = { counter: 0 };
handleClick = () => {
// ...
}
Um construtor não deve conter quaisquer efeitos colaterais ou assinaturas.
Parâmetros
props
: as props iniciais do componente.
Retornos
O constructor
não deve retornar nada.
Ressalvas
-
Não execute quaisquer efeitos colaterais ou assinaturas no construtor. Em vez disso, use
componentDidMount
para isso. -
Dentro de um construtor, você precisa chamar
super(props)
antes de qualquer outra instrução. Se você não fizer isso,this.props
seráundefined
enquanto o construtor é executado, o que pode ser confuso e causar erros. -
Construtor é o único lugar onde você pode atribuir
this.state
diretamente. Em todos os outros métodos, você precisa usarthis.setState()
em vez disso. Não chamesetState
no construtor. -
Quando você usa renderização do servidor, o construtor também será executado no servidor, seguido pelo método
render
. No entanto, os métodos de ciclo de vida comocomponentDidMount
oucomponentWillUnmount
não serão executados no servidor. -
Quando o Modo Restrito estiver ativado, o React chamará o
constructor
duas vezes no desenvolvimento e então descartará uma das instâncias. Isso ajuda você a perceber os efeitos colaterais acidentais que precisam ser movidos para fora doconstructor
.
componentDidCatch(error, info)
Se você definir componentDidCatch
, o React o chamará quando algum componente filho (incluindo filhos distantes) lançar um erro durante a renderização. Isso permite que você registre esse erro em um serviço de relatório de erros em produção.
Normalmente, ele é usado em conjunto com static getDerivedStateFromError
, que permite que você atualize o state em resposta a um erro e exiba uma mensagem de erro ao usuário. Um componente com esses métodos é chamado de limite de erro.
Parâmetros
-
error
: O erro que foi lançado. Na prática, geralmente será uma instância deError
, mas isso não é garantido porque o JavaScript permitethrow
qualquer valor, incluindo strings ou aténull
. -
info
: Um objeto contendo informações adicionais sobre o erro. Seu campocomponentStack
contém um rastreamento de pilha com o componente que lançou, bem como os nomes e locais de origem de todos os seus componentes pai. Em produção, os nomes dos componentes serão minimizados. Se você configurar o relatório de erros de produção, poderá decodificar a pilha de componentes usando mapas de origem da mesma forma que faria para pilhas de erros JavaScript regulares.
Retornos
componentDidCatch
não deve retornar nada.
Ressalvas
-
No passado, era comum chamar
setState
dentro decomponentDidCatch
para atualizar a UI e exibir a mensagem de erro de fallback. Isso está obsoleto em favor da definição destatic getDerivedStateFromError
. -
As compilações de produção e desenvolvimento do React diferem ligeiramente na forma como
componentDidCatch
trata os erros. No desenvolvimento, os erros serão propagados parawindow
, o que significa que qualquerwindow.onerror
ouwindow.addEventListener('error', callback)
interceptará os erros que foram capturados porcomponentDidCatch
. Em produção, em vez disso, os erros não serão propagados, o que significa que qualquer manipulador de erros ancestral só receberá erros não explicitamente capturados porcomponentDidCatch
.
componentDidMount()
Se você definir o método componentDidMount
, o React o chamará quando seu componente for adicionado (montado) na tela. Este é um lugar comum para iniciar a busca de dados, configurar assinaturas ou manipular os nós DOM.
Se você implementar componentDidMount
, geralmente precisará implementar outros métodos de ciclo de vida para evitar erros. Por exemplo, se componentDidMount
ler algum state ou props, você também deve implementar componentDidUpdate
para lidar com suas alterações e componentWillUnmount
para limpar o que componentDidMount
estava fazendo.
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();
}
// ...
}
Parâmetros
componentDidMount
não recebe nenhum parâmetro.
Retornos
componentDidMount
não deve retornar nada.
Ressalvas
-
Quando o Modo Restrito estiver ativado, no desenvolvimento o React chamará
componentDidMount
, em seguida chamará imediatamente [componentWillUnmount
,] (#componentwillunmount) e depois chamarácomponentDidMount
novamente. Isso ajuda você a notar se você se esqueceu de implementarcomponentWillUnmount
ou se sua lógica não “espelha” totalmente o quecomponentDidMount
faz. -
Embora você possa chamar
setState
imediatamente emcomponentDidMount
, é melhor evitar isso quando puder. Ele acionará uma renderização extra, mas isso acontecerá antes que o navegador atualize a tela. Isso garante que, mesmo que orender
seja chamado duas vezes nesse caso, o usuário não verá o estado intermediário. Use este padrão com cautela porque ele geralmente causa problemas de desempenho. Na maioria dos casos, você deve ser capaz de atribuir o estado inicial noconstructor
em vez disso. No entanto, pode ser necessário para casos como modais e dicas de ferramentas quando você precisa medir um nó DOM antes de renderizar algo que dependa de seu tamanho ou posição.
componentDidUpdate(prevProps, prevState, snapshot?)
Se você definir o método componentDidUpdate
, o React o chamará imediatamente após seu componente ter sido renderizado novamente com props ou state atualizados. Este método não é chamado para a renderização inicial.
Você pode usá-lo para manipular o DOM após uma atualização. Este também é um lugar comum para fazer solicitações de rede, desde que você compare as props atuais com as props anteriores (por exemplo, uma solicitação de rede pode não ser necessária se as props não tiverem sido alteradas). Normalmente, você o usaria em conjunto com componentDidMount
e 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();
}
// ...
}
Parâmetros
-
prevProps
: Props antes da atualização. CompareprevProps
comthis.props
para determinar o que mudou. -
prevState
: State antes da atualização. CompareprevState
comthis.state
para determinar o que mudou. -
snapshot
: Se você implementougetSnapshotBeforeUpdate
,snapshot
conterá o valor que você retornou desse método. Caso contrário, seráundefined
.
Retornos
componentDidUpdate
não deve retornar nada.
Ressalvas
-
componentDidUpdate
não será chamado seshouldComponentUpdate
for definido e retornarfalse
. -
A lógica dentro de
componentDidUpdate
geralmente deve ser encapsulada em condições que comparamthis.props
comprevProps
ethis.state
comprevState
. Caso contrário, há o risco de criar loops infinitos. -
Embora você possa chamar
setState
imediatamente emcomponentDidUpdate
, é melhor evitar isso quando puder. Ele acionará uma renderização extra, mas isso acontecerá antes que o navegador atualize a tela. Isso garante que, mesmo que orender
seja chamado duas vezes nesse caso, o usuário não verá o estado intermediário. Esse padrão geralmente causa problemas de desempenho, mas pode ser necessário para casos raros como modais e dicas de ferramentas quando você precisa medir um nó DOM antes de renderizar algo que dependa de seu tamanho ou posição.
componentWillMount()
componentWillReceiveProps(nextProps)
componentWillUpdate(nextProps, nextState)
componentWillUnmount()
Se você definir o método componentWillUnmount
, o React o chamará antes que seu componente seja removido (desmontado) da tela. Este é um lugar comum para cancelar a busca de dados ou remover assinaturas.
A lógica dentro de componentWillUnmount
deve “espelhar” a lógica dentro componentDidMount
. Por exemplo, se componentDidMount
configurar uma assinatura, componentWillUnmount
deve limpar essa assinatura. Se a lógica de limpeza em seu componentWillUnmount
lê algumas props ou state, você geralmente também precisará implementar componentDidUpdate
para limpar os recursos (como assinaturas) correspondentes às props e state antigas.
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();
}
// ...
}
Parâmetros
componentWillUnmount
não recebe nenhum parâmetro.
Retornos
componentWillUnmount
não deve retornar nada.
Ressalvas
- Quando o Strict Mode está ativado, no desenvolvimento, o React chamará
componentDidMount
, então chamará imediatamentecomponentWillUnmount
e, em seguida, chamarácomponentDidMount
novamente. Isso ajuda você a notar se esqueceu de implementarcomponentWillUnmount
ou se sua lógica não “espelha” totalmente o quecomponentDidMount
faz.
forceUpdate(callback?)
Força um componente a renderizar novamente.
Normalmente, isso não é necessário. Se o método render
do seu componente lê apenas de this.props
, this.state
ou this.context
, ele renderizará novamente automaticamente quando você chamar setState
dentro do seu componente ou de um de seus pais. No entanto, se o método render
do seu componente lê diretamente de uma fonte de dados externa, você deve dizer ao React para atualizar a interface do usuário quando essa fonte de dados mudar. É isso que forceUpdate
permite que você faça.
Tente evitar todos os usos de forceUpdate
e leia apenas de this.props
e this.state
em render
.
Parâmetros
- opcional
callback
Se especificado, o React chamará ocallback
que você forneceu após a confirmação da atualização.
Retorna
forceUpdate
não retorna nada.
Ressalvas
- Se você chamar
forceUpdate
, o React irá renderizar novamente sem chamarshouldComponentUpdate
.
getSnapshotBeforeUpdate(prevProps, prevState)
Se você implementar getSnapshotBeforeUpdate
, o React irá chamá-lo imediatamente antes que o React atualize o DOM. Ele permite que seu componente capture algumas informações do DOM (por exemplo, a posição da rolagem) antes que ele seja potencialmente alterado. Qualquer valor retornado por este método do ciclo de vida será passado como um parâmetro para componentDidUpdate
.
Por exemplo, você pode usá-lo em uma interface do usuário como um tópico de bate-papo que precisa preservar sua posição de rolagem durante as atualizações:
class ScrollingList extends React.Component {
constructor(props) {
super(props);
this.listRef = React.createRef();
}
getSnapshotBeforeUpdate(prevProps, prevState) {
// Estamos adicionando novos itens à lista?
// Capture a posição da rolagem para que possamos ajustar a rolagem mais tarde.
if (prevProps.list.length < this.props.list.length) {
const list = this.listRef.current;
return list.scrollHeight - list.scrollTop;
}
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
// Se tivermos um valor de snapshot, acabamos de adicionar novos itens.
// Ajuste a rolagem para que esses novos itens não empurrem os antigos para fora da exibição.
// (snapshot aqui é o valor retornado de getSnapshotBeforeUpdate)
if (snapshot !== null) {
const list = this.listRef.current;
list.scrollTop = list.scrollHeight - snapshot;
}
}
render() {
return (
<div ref={this.listRef}>{/* ...conteúdo... */}</div>
);
}
}
No exemplo acima, é importante ler a propriedade scrollHeight
diretamente em getSnapshotBeforeUpdate
. Não é seguro lê-la em render
, UNSAFE_componentWillReceiveProps
ou UNSAFE_componentWillUpdate
porque há uma possível lacuna de tempo entre a chamada desses métodos e a atualização do DOM pelo React.
Parâmetros
-
prevProps
: Props antes da atualização. CompareprevProps
comthis.props
para determinar o que mudou. -
prevState
: State antes da atualização. CompareprevState
comthis.state
para determinar o que mudou.
Retorna
Você deve retornar um valor de snapshot de qualquer tipo que desejar ou null
. O valor que você retornou será passado como o terceiro argumento para componentDidUpdate
.
Ressalvas
getSnapshotBeforeUpdate
não será chamado seshouldComponentUpdate
for definido e retornarfalse
.
render()
O método render
é o único método obrigatório em um componente de classe.
O método render
deve especificar o que você deseja que apareça na tela, por exemplo:
import { Component } from 'react';
class Greeting extends Component {
render() {
return <h1>Olá, {this.props.name}!</h1>;
}
}
O React pode chamar render
a qualquer momento, então você não deve presumir que ele seja executado em um momento específico. Normalmente, o método render
deve retornar um pedaço de JSX, mas alguns outros tipos de retorno (como strings) são suportados. Para calcular o JSX retornado, o método render
pode ler this.props
, this.state
e this.context
.
Você deve escrever o método render
como uma função pura, o que significa que ele deve retornar o mesmo resultado se as props, state e context forem os mesmos. Ele também não deve conter efeitos colaterais (como configurar assinaturas) ou interagir com as APIs do navegador. Efeitos colaterais devem acontecer em manipuladores de eventos ou métodos como componentDidMount
.
Parâmetros
render
não recebe nenhum parâmetro.
Retorna
render
pode retornar qualquer nó React válido. Isso inclui elementos React, como <div />
, strings, números, portais, nós vazios (null
, undefined
, true
e false
) e arrays de nós React.
Ressalvas
-
render
deve ser escrito como uma função pura de props, state e context. Não deve ter efeitos colaterais. -
render
não será chamado seshouldComponentUpdate
for definido e retornarfalse
. -
Quando o Strict Mode está ativado, o React chamará
render
duas vezes no desenvolvimento e depois descartará um dos resultados. Isso ajuda você a perceber os efeitos colaterais acidentais que precisam ser movidos de fora do métodorender
. -
Não há correspondência um-para-um entre a chamada
render
e a subsequente chamadacomponentDidMount
oucomponentDidUpdate
. Alguns dos resultados da chamadarender
podem ser descartados pelo React quando for benéfico.
setState(nextState, callback?)
Chame setState
para atualizar o state do seu 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>Olá, {this.state.name}.</p>
</>
);
}
}
setState
enfileira alterações no state do componente. Ele diz ao React que este componente e seus filhos precisam renderizar novamente com o novo state. Esta é a principal maneira de atualizar a interface do usuário em resposta às interações.
Você também pode passar uma função para setState
. Ele permite que você atualize o state com base no state anterior:
handleIncreaseAge = () => {
this.setState(prevState => {
return {
age: prevState.age + 1
};
});
}
Você não precisa fazer isso, mas é útil se quiser atualizar o state várias vezes durante o mesmo evento.
Parâmetros
-
nextState
: Um objeto ou uma função.- Se você passar um objeto como
nextState
, ele será superficialmente mesclado emthis.state
. - Se você passar uma função como
nextState
, ela será tratada como uma função atualizadora. Ela deve ser pura, deve receber o state e as props pendentes como argumentos e deve retornar o objeto a ser superficialmente mesclado emthis.state
. O React colocará sua função atualizadora em uma fila e renderizará novamente seu componente. Durante a próxima renderização, o React calculará o próximo state aplicando todos os atualizadores enfileirados ao state anterior.
- Se você passar um objeto como
-
opcional
callback
: Se especificado, o React chamará ocallback
que você forneceu após a confirmação da atualização.
Retorna
setState
não retorna nada.
Ressalvas
-
Pense em
setState
como uma solicitação em vez de um comando imediato para atualizar o componente. Quando vários componentes atualizam seu state em resposta a um evento, o React irá agrupar suas atualizações e renderizá-las juntas em uma única passagem no final do evento. No raro caso em que você precisa forçar que uma atualização de state específica seja aplicada de forma síncrona, você pode envolvê-la emflushSync
, mas isso pode prejudicar o desempenho. -
setState
não atualizathis.state
imediatamente. Isso torna a leitura dethis.state
logo após a chamadasetState
um possível problema. Em vez disso, usecomponentDidUpdate
ou o argumentocallback
de setState, cada um dos quais tem garantia de ser acionado após a aplicação da atualização. Se você precisar definir o state com base no state anterior, poderá passar uma função paranextState
, conforme descrito acima.
shouldComponentUpdate(nextProps, nextState, nextContext)
Se você definir shouldComponentUpdate
, o React irá chamá-lo para determinar se uma renderização novamente pode ser ignorada.
Se você está confiante de que deseja escrevê-lo manualmente, você pode comparar this.props
com nextProps
e this.state
com nextState
e retornar false
para dizer ao React que a atualização pode ser ignorada.
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
) {
// Nada mudou, então uma renderização novamente é desnecessária
return false;
}
return true;
}
// ...
}
O React chama shouldComponentUpdate
antes da renderização quando novas props ou state são recebidos. O padrão é true
. Este método não é chamado para a renderização inicial ou quando forceUpdate
é usado.
Parâmetros
nextProps
: As próximas props que o componente está prestes a renderizar. ComparenextProps
comthis.props
para determinar o que mudou.nextState
: O próximo state que o componente está prestes a renderizar. ComparenextState
comthis.state
para determinar o que mudou.nextContext
: O próximo context que o componente está prestes a renderizar. ComparenextContext
comthis.context
para determinar o que mudou. Disponível apenas se você especificarstatic contextType
.
Retorna
Retorne true
se você deseja que o componente renderize novamente. Esse é o comportamento padrão.
Retorne false
para dizer ao React que renderizar novamente pode ser ignorado.
Ressalvas
-
Este método só existe como uma otimização de desempenho. Se seu componente quebrar sem ele, corrija isso primeiro.
-
Considere usar
PureComponent
em vez de escrevershouldComponentUpdate
manualmente.PureComponent
compara superficialmente as props e o state e reduz a chance de que você ignore uma atualização necessária. -
Não recomendamos fazer verificações de igualdade profunda ou usar
JSON.stringify
emshouldComponentUpdate
. Isso torna o desempenho imprevisível e dependente da estrutura de dados de cada prop e state. No melhor dos casos, você corre o risco de introduzir paralisações de vários segundos em seu aplicativo e, no pior dos casos, corre o risco de travá-lo. -
Retornar
false
não impede que os componentes filhos renderizem novamente quando o seu state mudar. -
Retornar
false
não garante que o componente não irá renderizar novamente. O React usará o valor de retorno como uma dica, mas ainda poderá optar por renderizar novamente seu componente se fizer sentido fazê-lo por outros motivos.
UNSAFE_componentWillMount()
Se você definir UNSAFE_componentWillMount
, o React o chamará imediatamente após o constructor
. Ele existe apenas por razões históricas e não deve ser usado em nenhum código novo. Em vez disso, use uma das alternativas:
- Para inicializar o state, declare
state
como um campo de classe ou definathis.state
dentro doconstructor
. - Se você precisar executar um efeito colateral ou configurar uma assinatura, mova essa lógica para
componentDidMount
em vez disso.
Veja exemplos de como migrar de lifecycles inseguros.
Parâmetros
UNSAFE_componentWillMount
não recebe nenhum parâmetro.
Retorna
UNSAFE_componentWillMount
não deve retornar nada.
Ressalvas
-
UNSAFE_componentWillMount
não será chamado se o componente implementarstatic getDerivedStateFromProps
ougetSnapshotBeforeUpdate
. -
Apesar de sua nomenclatura,
UNSAFE_componentWillMount
não garante que o componente será montado se seu aplicativo usa recursos modernos do React, comoSuspense
. Se uma tentativa de renderização for suspensa (por exemplo, porque o código de algum componente filho ainda não foi carregado), o React jogará a árvore em andamento fora e tentará construir o componente do zero durante a próxima tentativa. É por isso que este método é “inseguro”. O código que depende da montagem (como adicionar uma assinatura) deve ir paracomponentDidMount
. -
UNSAFE_componentWillMount
é o único método do ciclo de vida que é executado durante a renderização do servidor. Para todos os efeitos práticos, ele é idêntico aoconstructor
, então você deve usar oconstructor
para esse tipo de lógica.
UNSAFE_componentWillReceiveProps(nextProps, nextContext)
Se você definir UNSAFE_componentWillReceiveProps
, o React irá chamá-lo quando o componente receber novas props. Ele existe apenas por razões históricas e não deve ser usado em nenhum código novo. Em vez disso, use uma das alternativas:
- Se você precisar executar um efeito colateral (por exemplo, buscar dados, executar uma animação ou reinicializar uma assinatura) em resposta a alterações de prop, mova essa lógica para
componentDidUpdate
em vez disso. - Se você precisar evitar o recálculo de alguns dados somente quando uma prop mudar, use um auxiliar de memoização em vez disso.
- Se você precisar “resetar” algum state quando uma prop mudar, considere tornar um componente totalmente controlado ou totalmente não controlado com uma chave em vez disso.
- Se você precisar “ajustar” algum state quando uma prop mudar, verifique se você pode calcular todas as informações necessárias apenas a partir das props durante a renderização. Se não for possível, use
static getDerivedStateFromProps
em vez disso.
Veja exemplos de como migrar de lifecycles inseguros.
Parâmetros ```text
nextProps
: As próximas props que o componente está prestes a receber de seu componente pai. ComparenextProps
comthis.props
para determinar o que mudou.nextContext
: O próximo contexto que o componente está prestes a receber do provedor mais próximo. ComparenextContext
comthis.context
para determinar o que mudou. Disponível somente se você especificarstatic contextType
.
Retorna
UNSAFE_componentWillReceiveProps
não deve retornar nada.
Ressalvas
-
UNSAFE_componentWillReceiveProps
não será chamado se o componente implementarstatic getDerivedStateFromProps
ougetSnapshotBeforeUpdate
. -
Apesar de seu nome,
UNSAFE_componentWillReceiveProps
não garante que o componente receberá essas props se seu aplicativo usar recursos modernos do React comoSuspense
. Se uma tentativa de renderização for suspensa (por exemplo, porque o código de algum componente filho ainda não foi carregado), o React descartará a árvore em andamento e tentará construir o componente do zero durante a próxima tentativa. No momento da próxima tentativa de renderização, as props podem ser diferentes. É por isso que este método é “unsafe”. O código que deve ser executado apenas para atualizações confirmadas (como redefinir uma assinatura) deve ir paracomponentDidUpdate
. -
UNSAFE_componentWillReceiveProps
não significa que o componente recebeu props diferentes da última vez. Você precisa compararnextProps
ethis.props
por conta própria para verificar se algo mudou. -
O React não chama
UNSAFE_componentWillReceiveProps
com as props iniciais durante a montagem. Ele só chama este método se algumas das props do componente forem atualizadas. Por exemplo, chamarsetState
não aciona geralmenteUNSAFE_componentWillReceiveProps
dentro do mesmo componente.
UNSAFE_componentWillUpdate(nextProps, nextState)
Se você definir UNSAFE_componentWillUpdate
, o React o chamará antes de renderizar com as novas props ou estado. Ele só existe por razões históricas e não deve ser usado em nenhum código novo. Em vez disso, use uma das alternativas:
- Se você precisar executar um efeito colateral (por exemplo, buscar dados, executar uma animação ou reinicializar uma assinatura) em resposta a alterações de prop ou estado, mova essa lógica para
componentDidUpdate
em vez disso. - Se você precisar ler algumas informações do DOM (por exemplo, para salvar a posição atual da rolagem) para que possa usá-la em
componentDidUpdate
posteriormente, leia-a dentro degetSnapshotBeforeUpdate
em vez disso.
Veja exemplos de como migrar de ciclos de vida inseguros.
Parâmetros
nextProps
: As próximas props que o componente está prestes a renderizar. ComparenextProps
comthis.props
para determinar o que mudou.nextState
: O próximo estado com o qual o componente está prestes a renderizar. ComparenextState
comthis.state
para determinar o que mudou.
Retorna
UNSAFE_componentWillUpdate
não deve retornar nada.
Ressalvas
-
UNSAFE_componentWillUpdate
não será chamado seshouldComponentUpdate
for definido e retornarfalse
. -
UNSAFE_componentWillUpdate
não será chamado se o componente implementarstatic getDerivedStateFromProps
ougetSnapshotBeforeUpdate
. -
Não é suportado chamar
setState
(ou qualquer método que leve asetState
ser chamado, como despachar uma ação do Redux) durantecomponentWillUpdate
. -
Apesar de seu nome,
UNSAFE_componentWillUpdate
não garante que o componente será atualizado se seu aplicativo usar recursos modernos do React comoSuspense
. Se uma tentativa de renderização for suspensa (por exemplo, porque o código de algum componente filho ainda não foi carregado), o React descartará a árvore em andamento e tentará construir o componente do zero durante a próxima tentativa. No momento da próxima tentativa de renderização, as props e o estado podem ser diferentes. É por isso que este método é “unsafe”. O código que deve ser executado apenas para atualizações confirmadas (como redefinir uma assinatura) deve ir paracomponentDidUpdate
. -
UNSAFE_componentWillUpdate
não significa que o componente recebeu props ou estado diferentes da última vez. Você precisa compararnextProps
comthis.props
enextState
comthis.state
por conta própria para verificar se algo mudou. -
O React não chama
UNSAFE_componentWillUpdate
com as props e o estado iniciais durante a montagem.
static contextType
Se você quiser ler this.context
do seu componente de classe, você deve especificar qual contexto ele precisa ler. O contexto que você especifica como static contextType
deve ser um valor criado anteriormente 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>
);
}
}
static defaultProps
Você pode definir static defaultProps
para definir as props padrão para a classe. Elas serão usadas para props undefined
e ausentes, mas não para props null
.
Por exemplo, aqui está como você define que a prop color
deve ser definida por padrão como 'blue'
:
class Button extends Component {
static defaultProps = {
color: 'blue'
};
render() {
return <button className={this.props.color}>click me</button>;
}
}
Se a prop color
não for fornecida ou for undefined
, ela será definida por padrão como 'blue'
:
<>
{/* this.props.color é "blue" */}
<Button />
{/* this.props.color é "blue" */}
<Button color={undefined} />
{/* this.props.color é null */}
<Button color={null} />
{/* this.props.color é "red" */}
<Button color="red" />
</>
static getDerivedStateFromError(error)
Se você definir static getDerivedStateFromError
, o React o chamará quando um componente filho (incluindo filhos distantes) lançar um erro durante a renderização. Isso permite que você exiba uma mensagem de erro em vez de limpar a UI.
Normalmente, ele é usado em conjunto com componentDidCatch
, que permite enviar o relatório de erro para algum serviço de análise. Um componente com esses métodos é chamado de borda de erro.
Parâmetros
error
: O erro que foi lançado. Na prática, geralmente será uma instância deError
, mas isso não é garantido porque o JavaScript permitethrow
qualquer valor, incluindo strings ou até mesmonull
.
Retorna
static getDerivedStateFromError
deve retornar o estado que diz ao componente para exibir a mensagem de erro.
Ressalvas
static getDerivedStateFromError
deve ser uma função pura. Se você deseja executar um efeito colateral (por exemplo, chamar um serviço de análise), também precisa implementarcomponentDidCatch
.
static getDerivedStateFromProps(props, state)
Se você definir static getDerivedStateFromProps
, o React o chamará logo antes de chamar o render
, tanto na montagem inicial quanto nas atualizações subsequentes. Ele deve retornar um objeto para atualizar o estado ou null
para não atualizar nada.
Este método existe para casos de uso raros, onde o estado depende de alterações nas props ao longo do tempo. Por exemplo, este componente Form
redefine o estado email
quando a prop userID
muda:
class Form extends Component {
state = {
email: this.props.defaultEmail,
prevUserID: this.props.userID
};
static getDerivedStateFromProps(props, state) {
// Sempre que o usuário atual mudar,
// Redefinir quaisquer partes do estado que estejam vinculadas a esse usuário.
// Neste exemplo simples, é apenas o e-mail.
if (props.userID !== state.prevUserID) {
return {
prevUserID: props.userID,
email: props.defaultEmail
};
}
return null;
}
// ...
}
Observe que este padrão requer que você mantenha um valor anterior da prop (como userID
) no estado (como prevUserID
).
Parâmetros
props
: As próximas props que o componente está prestes a renderizar.state
: O próximo estado com o qual o componente está prestes a renderizar.
Retorna
static getDerivedStateFromProps
retorna um objeto para atualizar o estado ou null
para não atualizar nada.
Ressalvas
-
Este método é disparado em cada renderização, independentemente da causa. Isso é diferente de
UNSAFE_componentWillReceiveProps
, que só é disparado quando os pais causam uma nova renderização e não como resultado de umsetState
local. -
Este método não tem acesso à instância do componente. Se você quiser, poderá reutilizar algum código entre
static getDerivedStateFromProps
e os outros métodos de classe, extraindo funções puras das props e do estado do componente fora da definição da classe.
Uso
Definindo um componente de classe
Para definir um componente React como uma classe, estenda a classe Component
integrada e defina um método render
:
import { Component } from 'react';
class Greeting extends Component {
render() {
return <h1>Hello, {this.props.name}!</h1>;
}
}
O React chamará seu método render
sempre que precisar descobrir o que exibir na tela. Normalmente, você retornará algum JSX dele. Seu método render
deve ser uma função pura:, ele só deve calcular o JSX.
Semelhante aos componentes de função, um componente de classe pode receber informações por props de seu componente pai. No entanto, a sintaxe para ler props é diferente. Por exemplo, se o componente pai renderizar <Greeting name="Taylor" />
, então você pode ler a prop name
de 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" /> </> ); }
Observe que Hooks (funções começando com use
, como useState
) não são compatíveis com componentes de classe.
Adicionando estado a um componente de classe
Para adicionar estado a uma classe, atribua um objeto a uma propriedade chamada state
. Para atualizar o estado, chame 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}> Increment age </button> <p>Hello, {this.state.name}. You are {this.state.age}.</p> </> ); } }
Adicionando métodos do ciclo de vida a um componente de classe
Existem alguns métodos especiais que você pode definir em sua classe.
Se você definir o método componentDidMount
, o React o chamará quando seu componente for adicionado (montado) à tela. O React chamará componentDidUpdate
após o seu componente renderizar novamente, devido a props ou estado alterados. O React chamará componentWillUnmount
depois que seu componente for removido (desmontado) da tela.
Se você implementar componentDidMount
, geralmente precisará implementar todos os três ciclos de vida para evitar erros. Por exemplo, se componentDidMount
lê algum estado ou props, você também precisa implementar componentDidUpdate
para lidar com suas alterações e componentWillUnmount
para limpar o que componentDidMount
estava fazendo.
Por exemplo, este componente ChatRoom
mantém uma conexão de chat sincronizada com props e 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(); } }```js import { Component } from 'react'; 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>Bem vindo(a) à sala {this.props.roomId}!</h1> </> ); } }
Observe que, em desenvolvimento, quando o Modo Strict está ativado, o React chamará componentDidMount
, chamará imediatamente componentWillUnmount
e, em seguida, chamará componentDidMount
novamente. Isso ajuda você a notar se você esqueceu de implementar componentWillUnmount
ou se sua lógica não “espelha” totalmente o que componentDidMount
faz.
Capturando erros de renderização com um limite de erro
Por padrão, se seu aplicativo lançar um erro durante a renderização, o React removerá sua UI da tela. Para evitar isso, você pode encapsular uma parte da sua UI em um limite de erro. Um limite de erro é um componente especial que permite que você mostre alguma UI de fallback em vez da parte que travou — por exemplo, uma mensagem de erro.
Para implementar um componente de limite de erro, você precisa fornecer static getDerivedStateFromError
que permite que você atualize o estado em resposta a um erro e exiba uma mensagem de erro ao usuário. Você também pode implementar opcionalmente componentDidCatch
para adicionar alguma lógica extra, por exemplo, para registrar o erro em um serviço de análise.
With captureOwnerStack
you can include the Owner Stack during development.
import * as React from 'react';
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// Atualize o estado para que a próxima renderização mostre a UI de fallback.
return { hasError: true };
}
componentDidCatch(error, info) {
logErrorToMyService(
error,
// Example "componentStack":
// in ComponentThatThrows (created by App)
// in ErrorBoundary (created by App)
// in div (created by App)
// in App
info.componentStack,
// Warning: `captureOwnerStack` is not available in production.
React.captureOwnerStack(),
);
}
render() {
if (this.state.hasError) {
// Você pode renderizar qualquer UI de fallback personalizada
return this.props.fallback;
}
return this.props.children;
}
}
Então você pode encapsular uma parte da sua árvore de componentes com ele:
<ErrorBoundary fallback={<p>Algo deu errado</p>}>
<Profile />
</ErrorBoundary>
Se Profile
ou seu componente filho lançarem um erro, ErrorBoundary
“capturará” esse erro, exibirá uma UI de fallback com a mensagem de erro que você forneceu e enviará um relatório de erro de produção para seu serviço de relatório de erro.
Você não precisa encapsular cada componente em um limite de erro separado. Quando você pensa sobre a granularidade dos limites de erro, considere onde faz sentido exibir uma mensagem de erro. Por exemplo, em um aplicativo de mensagens, faz sentido colocar um limite de erro ao redor da lista de conversas. Também faz sentido colocar um ao redor de cada mensagem individual. No entanto, não faria sentido colocar um limite em cada avatar.
Alternativas
Migrando um componente simples de uma classe para uma função
Normalmente, você irá definir componentes como funções em vez disso.
Por exemplo, suponha que você esteja convertendo este componente de classe Greeting
em uma função:
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" /> </> ); }
Defina uma função chamada Greeting
. É aqui que você moverá o corpo da sua função render
.
function Greeting() {
// ... mova o código do método render aqui ...
}
Em vez de this.props.name
, defina a name
prop usando a sintaxe de desestruturação e leia-a diretamente:
function Greeting({ name }) {
return <h1>Hello, {name}!</h1>;
}
Aqui está um exemplo completo:
function Greeting({ name }) { return <h1>Hello, {name}!</h1>; } export default function App() { return ( <> <Greeting name="Sara" /> <Greeting name="Cahal" /> <Greeting name="Edite" /> </> ); }
Migrando um componente com estado de uma classe para uma função
Suponha que você esteja convertendo este componente de classe Counter
em uma função:
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}> Increment age </button> <p>Hello, {this.state.name}. You are {this.state.age}.</p> </> ); } }
Comece declarando uma função com as variáveis de estado necessárias:
import { useState } from 'react';
function Counter() {
const [name, setName] = useState('Taylor');
const [age, setAge] = useState(42);
// ...
Em seguida, converta os manipuladores 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, substitua todas as referências começando com this
pelas variáveis e funções que você definiu em seu componente. Por exemplo, substitua this.state.age
por age
e substitua this.handleNameChange
por handleNameChange
.
Aqui está um componente totalmente 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}> Increment age </button> <p>Hello, {name}. You are {age}.</p> </> ) }
Migrando um componente com métodos de ciclo de vida de uma classe para uma função
Suponha que você esteja convertendo este componente de classe ChatRoom
com métodos de ciclo de vida em uma função:
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>Welcome to the {this.props.roomId} room!</h1> </> ); } }
Primeiro, verifique se seu componentWillUnmount
faz o oposto de componentDidMount
. No exemplo acima, isso é verdade: ele desconecta a conexão que componentDidMount
configura. Se essa lógica estiver faltando, adicione-a primeiro.
Em seguida, verifique se seu método componentDidUpdate
lida com as alterações em quaisquer props e estado que você está usando em componentDidMount
. No exemplo acima, componentDidMount
chama setupConnection
, que lê this.state.serverUrl
e this.props.roomId
. É por isso que componentDidUpdate
verifica se this.state.serverUrl
e this.props.roomId
foram alterados e redefinem a conexão, caso tenham sido. Se a lógica do seu componentDidUpdate
estiver faltando ou não manipular as alterações em todas as props e estado relevantes, corrija-a primeiro.
No exemplo acima, a lógica dentro dos métodos de ciclo de vida conecta o componente a um sistema fora do React (um servidor de bate-papo). Para conectar um componente a um sistema externo, descreva essa lógica como um único Efeito:
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 chamada useEffect
é equivalente à lógica nos métodos de ciclo de vida acima. Se seus métodos de ciclo de vida fizerem várias coisas não relacionadas, divida-os em vários Efeitos independentes. Aqui está um exemplo completo com o qual você pode brincar:
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>Bem vindo(a) à sala {roomId}!</h1> </> ); }
Migrando um componente com contexto de uma classe para uma função
Neste exemplo, os componentes de classe Panel
e Button
leem o contexto de 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="Welcome"> <Button>Sign up</Button> <Button>Log in</Button> </Panel> ); } export default function MyApp() { return ( <ThemeContext.Provider value="dark"> <Form /> </ThemeContext.Provider> ) }
Quando você os converte em componentes de função, substitua this.context
pelas chamadas [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="Welcome"> <Button>Sign up</Button> <Button>Log in</Button> </Panel> ); } export default function MyApp() { return ( <ThemeContext.Provider value="dark"> <Form /> </ThemeContext.Provider> ) }