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
Componentcontextpropsstateconstructor(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 contextTypestatic defaultPropsstatic 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
componentDidMountpara isso. -
Dentro de um construtor, você precisa chamar
super(props)antes de qualquer outra instrução. Se você não fizer isso,this.propsseráundefinedenquanto o construtor é executado, o que pode ser confuso e causar erros. -
Construtor é o único lugar onde você pode atribuir
this.statediretamente. Em todos os outros métodos, você precisa usarthis.setState()em vez disso. Não chamesetStateno 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 comocomponentDidMountoucomponentWillUnmountnão serão executados no servidor. -
Quando o Modo Restrito estiver ativado, o React chamará o
constructorduas 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 permitethrowqualquer valor, incluindo strings ou aténull. -
info: Um objeto contendo informações adicionais sobre o erro. Seu campocomponentStackconté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
setStatedentro decomponentDidCatchpara 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
componentDidCatchtrata os erros. No desenvolvimento, os erros serão propagados parawindow, o que significa que qualquerwindow.onerrorouwindow.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ácomponentDidMountnovamente. Isso ajuda você a notar se você se esqueceu de implementarcomponentWillUnmountou se sua lógica não “espelha” totalmente o quecomponentDidMountfaz. -
Embora você possa chamar
setStateimediatamente 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 orenderseja 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 noconstructorem 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. CompareprevPropscomthis.propspara determinar o que mudou. -
prevState: State antes da atualização. CompareprevStatecomthis.statepara determinar o que mudou. -
snapshot: Se você implementougetSnapshotBeforeUpdate,snapshotconterá o valor que você retornou desse método. Caso contrário, seráundefined.
Retornos
componentDidUpdate não deve retornar nada.
Ressalvas
-
componentDidUpdatenão será chamado seshouldComponentUpdatefor definido e retornarfalse. -
A lógica dentro de
componentDidUpdategeralmente deve ser encapsulada em condições que comparamthis.propscomprevPropsethis.statecomprevState. Caso contrário, há o risco de criar loops infinitos. -
Embora você possa chamar
setStateimediatamente 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 orenderseja 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á imediatamentecomponentWillUnmounte, em seguida, chamarácomponentDidMountnovamente. Isso ajuda você a notar se esqueceu de implementarcomponentWillUnmountou se sua lógica não “espelha” totalmente o quecomponentDidMountfaz.
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
callbackSe especificado, o React chamará ocallbackque 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. CompareprevPropscomthis.propspara determinar o que mudou. -
prevState: State antes da atualização. CompareprevStatecomthis.statepara 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
getSnapshotBeforeUpdatenão será chamado seshouldComponentUpdatefor 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
-
renderdeve ser escrito como uma função pura de props, state e context. Não deve ter efeitos colaterais. -
rendernão será chamado seshouldComponentUpdatefor definido e retornarfalse. -
Quando o Strict Mode está ativado, o React chamará
renderduas 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
rendere a subsequente chamadacomponentDidMountoucomponentDidUpdate. Alguns dos resultados da chamadarenderpodem 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á ocallbackque você forneceu após a confirmação da atualização.
Retorna
setState não retorna nada.
Ressalvas
-
Pense em
setStatecomo 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. -
setStatenão atualizathis.stateimediatamente. Isso torna a leitura dethis.statelogo após a chamadasetStateum possível problema. Em vez disso, usecomponentDidUpdateou o argumentocallbackde 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. ComparenextPropscomthis.propspara determinar o que mudou.nextState: O próximo state que o componente está prestes a renderizar. ComparenextStatecomthis.statepara determinar o que mudou.nextContext: O próximo context que o componente está prestes a renderizar. ComparenextContextcomthis.contextpara 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
PureComponentem vez de escrevershouldComponentUpdatemanualmente.PureComponentcompara 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.stringifyemshouldComponentUpdate. 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
falsenão impede que os componentes filhos renderizem novamente quando o seu state mudar. -
Retornar
falsenã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
statecomo um campo de classe ou definathis.statedentro doconstructor. - Se você precisar executar um efeito colateral ou configurar uma assinatura, mova essa lógica para
componentDidMountem 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_componentWillMountnão será chamado se o componente implementarstatic getDerivedStateFromPropsougetSnapshotBeforeUpdate. -
Apesar de sua nomenclatura,
UNSAFE_componentWillMountnã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 oconstructorpara 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
componentDidUpdateem 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 getDerivedStateFromPropsem 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. ComparenextPropscomthis.propspara determinar o que mudou.nextContext: O próximo contexto que o componente está prestes a receber do provedor mais próximo. ComparenextContextcomthis.contextpara determinar o que mudou. Disponível somente se você especificarstatic contextType.
Retorna
UNSAFE_componentWillReceiveProps não deve retornar nada.
Ressalvas
-
UNSAFE_componentWillReceivePropsnão será chamado se o componente implementarstatic getDerivedStateFromPropsougetSnapshotBeforeUpdate. -
Apesar de seu nome,
UNSAFE_componentWillReceivePropsnã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_componentWillReceivePropsnão significa que o componente recebeu props diferentes da última vez. Você precisa compararnextPropsethis.propspor conta própria para verificar se algo mudou. -
O React não chama
UNSAFE_componentWillReceivePropscom as props iniciais durante a montagem. Ele só chama este método se algumas das props do componente forem atualizadas. Por exemplo, chamarsetStatenão aciona geralmenteUNSAFE_componentWillReceivePropsdentro 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
componentDidUpdateem 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
componentDidUpdateposteriormente, leia-a dentro degetSnapshotBeforeUpdateem 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. ComparenextPropscomthis.propspara determinar o que mudou.nextState: O próximo estado com o qual o componente está prestes a renderizar. ComparenextStatecomthis.statepara determinar o que mudou.
Retorna
UNSAFE_componentWillUpdate não deve retornar nada.
Ressalvas
-
UNSAFE_componentWillUpdatenão será chamado seshouldComponentUpdatefor definido e retornarfalse. -
UNSAFE_componentWillUpdatenão será chamado se o componente implementarstatic getDerivedStateFromPropsougetSnapshotBeforeUpdate. -
Não é suportado chamar
setState(ou qualquer método que leve asetStateser chamado, como despachar uma ação do Redux) durantecomponentWillUpdate. -
Apesar de seu nome,
UNSAFE_componentWillUpdatenã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_componentWillUpdatenão significa que o componente recebeu props ou estado diferentes da última vez. Você precisa compararnextPropscomthis.propsenextStatecomthis.statepor conta própria para verificar se algo mudou. -
O React não chama
UNSAFE_componentWillUpdatecom 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 permitethrowqualquer 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 getDerivedStateFromErrordeve 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 umsetStatelocal. -
Este método não tem acesso à instância do componente. Se você quiser, poderá reutilizar algum código entre
static getDerivedStateFromPropse 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 value="dark"> <Form /> </ThemeContext> ) }
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 value="dark"> <Form /> </ThemeContext> ) }