Componentes, Elementos e Instâncias
Aprenda os conceitos fundamentais do React: como componentes, elementos e instâncias trabalham juntos para construir aplicações web modernas.
React Components, Elements and Instances
A meta deste blog e posts subsequentes é introduzir ao React, fomentar conhecimento, fixar ideias, conceitos e fundamentos sobre tecnologias. Para isto abordarei os temas do básico ao avançado, tentando ser minucioso. Desde já expresso minha gratidão aos leitores. Então vamos ao React - temos que entender seu funcionamento e arquitetura.
Definição e História
React é uma biblioteca JavaScript criada pelo Facebook (Meta) em meados de 2013 e desde então foi se popularizando e reduzindo o uso de jQuery (2006). Na era jQuery, este veio com a proposta de facilitar a manipulação
do DOM, para isto ele provê queries para acessar diretamente o DOM. Isto era melhor do que usar diretamente seletores document.getElementById, getElementsByClassName e outros.
Ao longo dos anos jQuery foi se tornando pesado e complexo devido à escala e complexidade dos projetos web, bibliotecas como React, Vue, Angular e experimentos como hell.js começaram a surgir e serem adotadas gradativamente. React se tornou popular e hoje é uma das bibliotecas mais usadas.
Princípio
Componentes, Elementos e Instâncias são conceitos fundamentais para compreensão de como o React opera.
Componentes no react são funções ou classes que retornam elementos React, são reutilizáveis e contêm lógica de comportamento, UI e estado. O React vem com a premissa de compor a UI através de componentes, reutilizar estes componentes e fazer a gestão de estado ligados à UI nestes componentes. Em sua forma primária, React é uma biblioteca que transforma componentes em elementos e estes em instâncias que são renderizadas no DOM. Podemos pensar nos componentes como projetos arquitetônicos, os elementos como os desenhos técnicos e as instâncias como a construção física.
Componente React
Elemento React
Instância no DOM
function Button() {
return <button>Click</button>;
}
// Ou classe
class Button extends React.Component {
render() {
return <button>Click</button>;
}
}const element = <Button />;
// Representa:
{
type: Button,
props: {},
key: null,
ref: null
}ReactDOM.render(
element,
container
);
// Resultado no DOM:
<button>Click</button>Evolução dos Seletores DOM
Para entender melhor o valor que React traz, vamos comparar como a mesma funcionalidade evoluiu ao longo do tempo:
// Seleção de elementos
const button = document.getElementById('myButton');
const items = document.getElementsByClassName('item');
const links = document.querySelectorAll('a.external');
// Evento de de click direto no DOM
button.addEventListener('click', function() {
const newDiv = document.createElement('div');
newDiv.className = 'message';
newDiv.textContent = 'Clicou!';
document.body.appendChild(newDiv);
});
// Atualização de elementos no DOM
const list = document.getElementById('todoList');
list.innerHTML = '';
todos.forEach(function(todo) {
const li = document.createElement('li');
li.textContent = todo.text;
if (todo.completed) {
li.className = 'completed';
}
list.appendChild(li);
});
// Seleção de elementos
const $button = $('#myButton');
const $items = $('.item');
const $links = $('a.external');
// Evento de de click direto no DOM
$button.on('click', function() {
$('<div>')
.addClass('message')
.text('Clicou!')
.appendTo('body');
});
// Atualização de elementos no DOM
const $list = $('#todoList');
$list.empty();
$.each(todos, function(index, todo) {
$('<li>')
.text(todo.text)
.toggleClass('completed', todo.completed)
.appendTo($list);
});
// Componente React
function TodoList({ todos }) {
const [message, setMessage] = useState('');
const handleClick = () => {
setMessage('Clicou!');
};
return (
<div>
<button onClick={handleClick}>
Clique aqui
</button>
{message && <div className="message">{message}</div>}
<ul>
{todos.map(todo => (
<li
key={todo.id}
className={todo.completed ? 'completed' : ''}
>
{todo.text}
</li>
))}
</ul>
</div>
);
}Performance e Otimização
Um dos principais benefícios do React é a otimização de performance através do Virtual DOM. Vamos entender as diferenças de performance entre as abordagens:
Manipulação Direta do DOM
// ❌ Problema: Múltiplas operações custosas no DOM
function updateList(items) {
const list = document.getElementById('list');
// Cada operação causa reflow/repaint
list.innerHTML = ''; // Reflow 1
items.forEach(item => {
const li = document.createElement('li'); // Reflow 2
li.textContent = item.name;
list.appendChild(li); // Reflow 3, 4, 5...
});
}
// Resultado: 1 + N reflows (muito custoso!)Problemas:
- Cada alteração no DOM causa reflow/repaint
- Sem otimização automática
- Difícil de otimizar manualmente
- Performance degrada com escala
jQuery - Melhor, mas ainda limitado
// ⚠️ Melhor, mas ainda manipula DOM diretamente
function updateList(items) {
const $list = $('#list');
// Reduz reflows usando fragment
$list.empty(); // Reflow 1
const fragment = $(document.createDocumentFragment());
items.forEach(item => {
fragment.append(
$('<li>').text(item.name)
);
});
$list.append(fragment); // Reflow 2
}
// Resultado: 2 reflows (melhor, mas manual)Problemas:
- Requer otimização manual (fragments)
- Ainda manipula DOM diretamente
- Sem comparação inteligente
- Desenvolvedores frequentemente esquecem otimizar
React - Virtual DOM e Reconciliação
// ✅ React otimiza automaticamente
function List({ items }) {
return (
<ul>
{items.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}
// React internamente:
// 1. Cria Virtual DOM (JavaScript puro)
// 2. Compara com Virtual DOM anterior (diff)
// 3. Calcula mudanças mínimas necessárias
// 4. Aplica apenas mudanças no DOM real
// 5. Agrupa operações (batching)Vantagens:
- ✅ Virtual DOM: Operações em JavaScript (rápido)
- ✅ Diffing: Calcula mudanças mínimas
- ✅ Batching: Agrupa updates
- ✅ Reconciliação: Reutiliza elementos existentes
- ✅ Automático: Sem código extra
Como o Virtual DOM Funciona
O Virtual DOM é uma representação leve da árvore DOM mantida em memória. É essencialmente um objeto JavaScript que espelha a estrutura do DOM real, mas sem os custos computacionais de manipulação direta.
Ciclo de Atualização:
- Renderização Inicial: React cria o Virtual DOM e o DOM real correspondente
- Mudança de Estado: Quando o estado muda, React cria um novo Virtual DOM
- Diffing (Reconciliação): React compara o novo Virtual DOM com o anterior
- Cálculo de Mudanças: Identifica exatamente quais nós mudaram
- Commit: Aplica apenas as mudanças necessárias ao DOM real em lote
1. Estado Inicial
2. Novo Estado
3. Update Mínimo
// Virtual DOM
{
type: 'ul',
children: [
{ type: 'li', text: 'Item 1' },
{ type: 'li', text: 'Item 2' }
]
}
// DOM Real
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>// Virtual DOM atualizado
{
type: 'ul',
children: [
{ type: 'li', text: 'Item 1' },
{ type: 'li', text: 'Item 2' },
{ type: 'li', text: 'Item 3' }
]
}
// React faz diff
// Detecta: +1 novo item// React aplica apenas:
ul.appendChild(
createElement('li', 'Item 3')
);
// DOM Real final
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li> ← apenas isto mudou
</ul>Por que o Virtual DOM é eficiente?
- Operações em Memória: Manipular objetos JavaScript é muito mais rápido que manipular o DOM
- Batching: React agrupa múltiplas mudanças em uma única atualização do DOM
- Algoritmo de Diff Otimizado: Complexidade O(n) ao invés de O(n³) de algoritmos tradicionais de diff de árvore
- Heurísticas Inteligentes:
- Elementos de tipos diferentes geram árvores completamente diferentes
- Elementos com keys permitem identificação consistente entre renderizações
- Mudanças de propriedades não recriam o elemento, apenas atualizam atributos
Quando cada abordagem faz sentido
JavaScript Vanilla:
- ✅ Projetos muito simples
- ✅ Performance crítica em operações isoladas
- ✅ Sem dependências
- ❌ Apps complexas com estado
jQuery:
- ✅ Projetos legados
- ✅ Manipulações simples do DOM
- ✅ Compatibilidade com navegadores antigos
- ❌ SPAs modernas
React:
- ✅ Single Page Applications (SPAs)
- ✅ Interfaces complexas com muito estado
- ✅ Performance em escala
- ✅ Manutenibilidade e componentização
- ❌ Sites estáticos simples (overkill)