<h2>useState: Gerenciando Estado em Componentes Funcionais</h2>
<p>O <code>useState</code> é o hook fundamental do React que permite adicionar estado a componentes funcionais. Antes dos hooks, apenas componentes de classe podiam ter estado. Ele retorna um array com dois elementos: o valor atual do estado e uma função para atualizá-lo.</p>
<pre><code class="language-jsx">import { useState } from 'react';
function Contador() {
const [count, setCount] = useState(0);
const [nome, setNome] = useState('');
return (
<div>
<p>Contagem: {count}</p>
<button onClick={() => setCount(count + 1)}>Incrementar</button>
<input
value={nome}
onChange={(e) => setNome(e.target.value)}
placeholder="Digite seu nome"
/>
<p>Olá, {nome}!</p>
</div>
);
}</code></pre>
<p>Um detalhe crucial: quando você chama <code>setCount(count + 1)</code>, o React não atualiza o estado imediatamente no síncrono. Ele marca o componente para re-renderização e agenda a atualização. Se você precisar do novo valor imediatamente, use a versão funcional: <code>setCount(prevCount => prevCount + 1)</code>. Esta abordagem é especialmente importante em loops ou quando múltiplas atualizações ocorrem em sequência.</p>
<h2>useEffect: Efeitos Colaterais e Ciclo de Vida</h2>
<p>O <code>useEffect</code> executa código após a renderização. Ele substitui os métodos de ciclo de vida <code>componentDidMount</code>, <code>componentDidUpdate</code> e <code>componentWillUnmount</code> de componentes de classe. O segundo argumento é a <strong>dependency array</strong> — um array que controla quando o efeito roda novamente.</p>
<pre><code class="language-jsx">import { useState, useEffect } from 'react';
function Usuario({ id }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
setLoading(true);
fetch(https://jsonplaceholder.typicode.com/users/${id})
.then(res => res.json())
.then(data => {
setUser(data);
setLoading(false);
})
.catch(err => {
console.error(err);
setLoading(false);
});
// Cleanup function (desmontagem ou antes do próximo efeito)
return () => {
console.log('Limpando recursos para o usuário:', id);
};
}, [id]); // Rodar novamente apenas quando 'id' mudar
if (loading) return <p>Carregando...</p>;
if (!user) return <p>Usuário não encontrado</p>;
return <h1>{user.name}</h1>;
}</code></pre>
<p>As dependency arrays funcionam assim: <strong>sem array</strong> = executa após cada render; <strong>array vazio</strong> = executa apenas uma vez (montagem); <strong>array com valores</strong> = executa quando esses valores mudam. A função retornada é o cleanup, chamada antes do efeito rodar novamente ou quando o componente desmonta. Use para cancelar requisições, remover listeners ou liberar memória.</p>
<h2>useRef: Acessando Elementos DOM e Armazenando Valores Mutáveis</h2>
<p>O <code>useRef</code> cria uma referência persistente que não causa re-renderização ao ser alterada. Diferente do <code>useState</code>, mudar um ref não dispara atualização do componente. Use para acessar diretamente elementos do DOM ou para armazenar valores que precisam persistir entre renders sem afetar a lógica de renderização.</p>
<pre><code class="language-jsx">import { useRef, useState } from 'react';
function FormularioComFoco() {
const inputRef = useRef(null);
const renderCountRef = useRef(0);
const [nome, setNome] = useState('');
const focarNoInput = () => {
inputRef.current.focus();
};
const handleChange = () => {
renderCountRef.current += 1;
console.log(Render #${renderCountRef.current});
};
return (
<div>
<input
ref={inputRef}
value={nome}
onChange={(e) => {
setNome(e.target.value);
handleChange();
}}
placeholder="Digite algo"
/>
<button onClick={focarNoInput}>Focar no Input</button>
<p>O input foi alterado {renderCountRef.current} vezes</p>
</div>
);
}</code></pre>
<p><strong>Cuidado</strong>: evite usar refs para tudo. Se você quer contar renders, use <code>useState</code>. Refs são para casos específicos: controlar foco, disparar animações, integrar com bibliotecas de terceiros que manipulam o DOM diretamente, ou armazenar valores que não afetam a renderização.</p>
<h2>useCallback: Otimizando Funções e Evitando Re-renderizações Desnecessárias</h2>
<p>O <code>useCallback</code> memoriza uma função, retornando a mesma referência entre renders enquanto suas dependências não mudarem. Isso é crítico quando você passa callbacks como props para componentes filhos otimizados com <code>React.memo</code>, pois evita re-renderizações desnecessárias.</p>
<pre><code class="language-jsx">import { useState, useCallback } from 'react';
function ListaTarefas() {
const [tarefas, setTarefas] = useState(['Estudar', 'Exercitar']);
const [input, setInput] = useState('');
// Sem useCallback, uma nova função é criada a cada render
// Se PassarParaFilho estiver em React.memo, vai re-renderizar sempre
const adicionarTarefa = useCallback(() => {
if (input.trim()) {
setTarefas([...tarefas, input]);
setInput('');
}
}, [input, tarefas]); // Recriar quando input ou tarefas mudam
return (
<div>
<input
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Nova tarefa"
/>
<BotaoAdicionar onClick={adicionarTarefa} />
<ul>
{tarefas.map((t, i) => <li key={i}>{t}</li>)}
</ul>
</div>
);
}
const BotaoAdicionar = React.memo(({ onClick }) => {
console.log('BotaoAdicionar renderizado');
return <button onClick={onClick}>Adicionar</button>;
});</code></pre>
<p>Não otimize prematuramente. Use <code>useCallback</code> quando: (1) a função é passada como prop para componentes otimizados com <code>React.memo</code>, ou (2) a função é dependência de outros hooks como <code>useEffect</code> e <code>useCallback</code>. Se usá-lo sem necessidade, apenas adiciona complexidade.</p>
<h2>Conclusão</h2>
<p><strong>useState</strong> permite que componentes funcionais tenham estado reativo e re-renderizem quando mudam. <strong>useEffect</strong> executa efeitos colaterais em momentos específicos do ciclo de vida, com cleanup automático. <strong>useRef</strong> fornece acesso mutável a valores e elementos DOM sem disparar re-renderizações. <strong>useCallback</strong> memoriza funções para otimizar performance em cenários específicos. Domine esses quatro e você terá 80% do que precisa para React moderno. A chave é entender <strong>quando</strong> usar cada um, não apenas como.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://react.dev/reference/react/hooks" target="_blank" rel="noopener noreferrer">React Hooks Documentation - Official</a></li>
<li><a href="https://react.dev/reference/react/useState" target="_blank" rel="noopener noreferrer">useState, useEffect na Documentação React</a></li>
<li><a href="https://react.dev/reference/react/useRef" target="_blank" rel="noopener noreferrer">useRef and useCallback Guide</a></li>
<li><a href="https://web.dev/react/" target="_blank" rel="noopener noreferrer">React Hooks: A Introdução Completa (Web.dev)</a></li>
<li><a href="https://kentcdodds.com/blog/react-hooks" target="_blank" rel="noopener noreferrer">Clean Code in React: Hooks Best Practices</a></li>
</ul>