ReactJS - Ciclo de Vida do Componente
Olá aí, futuros desenvolvedores React! Hoje, vamos embarcar em uma jornada emocionante pelo ciclo de vida dos componentes React. Não se preocupe se você é novo em programação - Eu vou ser o seu guia amigável, explicando tudo passo a passo. No final deste tutorial, você terá uma compreensão sólida de como os componentes React nascem, crescem e, eventualmente, dizem adeus. Vamos começar!
O que é o Ciclo de Vida?
Antes de mergulharmos no código, vamos falar sobre o que queremos dizer com "ciclo de vida". Assim como nós, humanos, passamos por diferentes estágios na vida (nascimento, crescimento e, bem, você sabe...), os componentes React também têm suas próprias etapas de vida. Essas etapas são chamadas de ciclo de vida do componente.
Pense em um componente React como um pet virtual. Quando você o cria pela primeira vez, ele nasce. Então ele cresce e muda à medida que você interage com ele. Finalmente, quando você não precisa mais dele, ele some. Entender esse ciclo de vida é crucial para criar aplicações React dinâmicas e eficientes.
As Três Principais Fases de um Componente
Os componentes React passam por três principais fases:
- Montagem (Nascimento)
- Atualização (Crescimento)
- Desmontagem (Adeus)
Vamos explorar cada uma dessas fases e os métodos associados a elas.
1. Fase de Montagem
Esta é a fase em que nosso componente nasce e é adicionado ao DOM (Modelo de Objeto do Documento - pense nele como a árvore familiar da sua página da web).
Métodos-chave nesta fase:
Método | Descrição |
---|---|
constructor() | O construtor do componente, chamado antes de ser montado |
render() | O método que realmente rende o componente |
componentDidMount() | Chamado após o componente ser montado no DOM |
Vamos ver um exemplo simples:
import React, { Component } from 'react';
class BabyComponent extends Component {
constructor(props) {
super(props);
this.state = { message: "Acabei de nascer!" };
console.log("Constructor: Olá, estou sendo criado!");
}
componentDidMount() {
console.log("componentDidMount: Agora estou no DOM!");
}
render() {
console.log("Render: Estou sendo renderizado!");
return <h1>{this.state.message}</h1>;
}
}
export default BabyComponent;
Neste exemplo, nosso BabyComponent
passa pela fase de nascimento. O constructor
é chamado primeiro, configurando o estado inicial. Então render
é chamado para criar os elementos do DOM. Finalmente, componentDidMount
é chamado, indicando que nosso componente está completamente nascido e adicionado ao DOM.
2. Fase de Atualização
Esta fase ocorre quando o estado de um componente muda ou quando ele recebe novas props.
Métodos-chave nesta fase:
Método | Descrição |
---|---|
shouldComponentUpdate() | Decide se o componente deve ser re-renderizado |
render() | Re-rende o componente com dados atualizados |
componentDidUpdate() | Chamado após o componente ser atualizado |
Vamos estender o nosso exemplo anterior:
import React, { Component } from 'react';
class GrowingComponent extends Component {
constructor(props) {
super(props);
this.state = { age: 0 };
}
componentDidMount() {
this.ageInterval = setInterval(() => {
this.setState(prevState => ({ age: prevState.age + 1 }));
}, 1000);
}
shouldComponentUpdate(nextProps, nextState) {
return nextState.age % 5 === 0; // Apenas atualiza a cada 5 anos
}
componentDidUpdate() {
console.log(`Acabei de fazer ${this.state.age} anos!`);
}
render() {
return <h1>Tenho {this.state.age} anos</h1>;
}
componentWillUnmount() {
clearInterval(this.ageInterval);
}
}
export default GrowingComponent;
Neste exemplo, nosso GrowingComponent
"envelhece" a cada segundo. O método shouldComponentUpdate
garante que apenas festejamos aniversários a cada 5 anos (para economizar bolo, sabe). Quando o componente é atualizado, componentDidUpdate
registra uma mensagem de parabéns.
3. Fase de Desmontagem
Esta é a fase de despedida, quando um componente é removido do DOM.
Método-chave nesta fase:
Método | Descrição |
---|---|
componentWillUnmount() | Chamado pouco antes do componente ser desmontado e destruído |
Em nosso exemplo GrowingComponent
acima, usamos componentWillUnmount
para limpar o intervalo que configuramos, evitando vazamentos de memória.
Exemplo de API do Ciclo de Vida
Agora, vamos juntar tudo em um exemplo mais complexo. Vamos criar um aplicativo simples "Monitor de Humor" que demonstra todos os métodos do ciclo de vida.
import React, { Component } from 'react';
class MoodTracker extends Component {
constructor(props) {
super(props);
this.state = { mood: 'neutro', intensity: 5 };
console.log('Constructor: O Monitor de Humor está sendo criado');
}
componentDidMount() {
console.log('ComponentDidMount: O Monitor de Humor está agora no DOM');
this.moodInterval = setInterval(() => {
const moods = ['feliz', 'triste', 'empolgado', 'nervoso', 'neutro'];
const newMood = moods[Math.floor(Math.random() * moods.length)];
this.setState({ mood: newMood });
}, 5000);
}
shouldComponentUpdate(nextProps, nextState) {
return this.state.mood !== nextState.mood;
}
componentDidUpdate() {
console.log(`Humor atualizado para: ${this.state.mood}`);
}
componentWillUnmount() {
console.log('ComponentWillUnmount: Adeus Monitor de Humor!');
clearInterval(this.moodInterval);
}
handleIntensityChange = (e) => {
this.setState({ intensity: e.target.value });
}
render() {
console.log('Render: O Monitor de Humor está renderizando');
return (
<div>
<h1>Humor Atual: {this.state.mood}</h1>
<input
type="range"
min="1"
max="10"
value={this.state.intensity}
onChange={this.handleIntensityChange}
/>
<p>Intensidade: {this.state.intensity}</p>
</div>
);
}
}
export default MoodTracker;
Este componente MoodTracker
demonstra todos os métodos do ciclo de vida que discutimos. Ele muda o humor aleatoriamente a cada 5 segundos e permite ao usuário ajustar a intensidade do humor.
API do Ciclo de Vida em um Aplicativo de Gestão de Despesas
Agora, vamos considerar como poderíamos usar esses métodos do ciclo de vida em uma aplicação prática como um Gestor de Despesas.
import React, { Component } from 'react';
class ExpenseManager extends Component {
constructor(props) {
super(props);
this.state = { expenses: [], total: 0 };
}
componentDidMount() {
// Simula a busca de despesas de uma API
setTimeout(() => {
const fetchedExpenses = [
{ id: 1, description: 'Compras', amount: 50 },
{ id: 2, description: 'Gasolina', amount: 30 },
{ id: 3, description: 'Ingressos para o cinema', amount: 20 },
];
this.setState({ expenses: fetchedExpenses }, this.calculateTotal);
}, 1000);
}
shouldComponentUpdate(nextProps, nextState) {
// Apenas atualiza se o total mudar
return this.state.total !== nextState.total;
}
componentDidUpdate() {
console.log(`Total de despesas atualizado: $${this.state.total}`);
}
calculateTotal = () => {
const total = this.state.expenses.reduce((sum, expense) => sum + expense.amount, 0);
this.setState({ total });
}
render() {
return (
<div>
<h1>Gestor de Despesas</h1>
<ul>
{this.state.expenses.map(expense => (
<li key={expense.id}>{expense.description}: ${expense.amount}</li>
))}
</ul>
<h2>Total: ${this.state.total}</h2>
</div>
);
}
}
export default ExpenseManager;
Neste componente ExpenseManager
:
- Usamos
componentDidMount
para simular a busca de dados de despesas de uma API quando o componente é carregado pela primeira vez. -
shouldComponentUpdate
garante que apenas re-renderizamos quando o total muda, não para cada pequena atualização. -
componentDidUpdate
registra o novo total sempre que ele muda.
Ao usar esses métodos do ciclo de vida, criamos uma aplicação de rastreamento de despesas mais eficiente e responsiva.
Entender o ciclo de vida do componente é crucial para construir aplicações React eficientes. Ele permite que você controle quando ocorrem certas ações, otimize o desempenho e gerencie recursos de forma eficaz. Continue praticando com esses conceitos e em breve você estará criando aplicações React complexas e dinâmicas com facilidade!
Credits: Image by storyset