O que é React?
React é uma biblioteca JavaScript para a construção de interfaces de usuário a partir de componentes. Um componente é uma função que retorna marcação, e você compõe esses componentes para construir uma página. Em vez de dizer ao navegador como alterar o DOM passo a passo, você descreve como a UI deve ser com base nos dados atuais, e o React resolve as atualizações.
Essa mudança é chamada de renderização declarativa, e foi o motivo do React parecer tão diferente em 2013. Você deixa de escrever “encontre este elemento, altere seu texto, alterne aquela classe” e passa a escrever “dado este estado, aqui está a tela”. A parte complexa — comparar e atualizar o DOM de forma eficiente — torna-se responsabilidade do React.
Componentes e JSX
Um componente React é uma função cujo nome começa com letra maiúscula e que retorna JSX.
// Welcome.jsx
function Welcome({ name }) {
return <h1>Hello, {name}!</h1>;
}
export default function App() {
return (
<main>
<Welcome name="Ada" />
<Welcome name="Grace" />
</main>
);
}
O JSX se parece com HTML, mas é JavaScript. Chaves são usadas para incorporar expressões, e o compilador traduz cada elemento em uma chamada de função. Como os componentes são apenas funções, você pode compô-los, aninhá-los e reutilizá-los da mesma forma que reutilizaria qualquer outra função.
Props
Props são as entradas de um componente. Elas fluem para baixo, do pai para o filho, e são somente leitura — um filho nunca deve mutar suas props.
// Card.jsx
function Card({ title, children, variant = "default" }) {
return (
<article className={`card card--${variant}`}>
<h3>{title}</h3>
{children}
</article>
);
}
A prop children é qualquer conteúdo que você aninhe entre as tags de abertura e fechamento, o que torna os componentes wrappers compostíveis. Valores padrão permitem que quem chama o componente omita props que geralmente permanecem as mesmas.
Estado com useState
As props são fixas para uma renderização específica. O Estado (state) são dados que pertencem a um componente e podem mudar ao longo do tempo. O hook useState cria um valor de estado e uma função de atualização (setter).
// Search.jsx
import { useState } from "react";
function Search({ onSearch }) {
const [query, setQuery] = useState("");
return (
<form onSubmit={(e) => { e.preventDefault(); onSearch(query); }}>
<input
value={query}
onChange={(e) => setQuery(e.target.value)}
/>
</form>
);
}
Chamar o setter agenda uma nova renderização com o novo valor. As atualizações de estado são assíncronas e agrupadas (batched), e elas substituem em vez de mesclar; portanto, sempre crie um novo objeto ou array ao atualizar estados estruturados.
// update.jsx
setUser((prev) => ({ ...prev, name: "Grace" }));
setItems((prev) => [...prev, newItem]);
Usar a forma de função de atualização (updater function) garante a segurança quando o próximo valor depende do valor anterior.
Renderizando listas e condições
O React não possui uma linguagem de template para loops e ramificações — você utiliza JavaScript puro.
// List.jsx
function List({ items }) {
if (items.length === 0) return <p>Nothing here yet.</p>;
return (
<ul>
{items.map((item) => (
<li key={item.id}>{item.label}</li>
))}
</ul>
);
}
A prop key é obrigatória para itens de lista. Atribua a ela um valor estável e único dos seus dados para que o React consiga associar os itens corretamente entre as renderizações. O operador ternário e o && resolvem condições inline, embora retornos antecipados (early returns) geralmente tornem a leitura mais clara.
Eventos
Os eventos no React utilizam props em camelCase e recebem um objeto de evento sintético.
// Button.jsx
<button
onClick={(event) => {
event.preventDefault();
submit();
}}
>
Save
</button>
Passar uma função para a prop é fundamental — onClick={submit()} a chamaria imediatamente durante a renderização. Quando um handler precisar de um argumento, envolva-o em uma arrow function.
Effects com useEffect
useEffect sincroniza seu componente com sistemas fora do React: requisições de rede, subscriptions, timers e manipulações diretas no DOM.
// Users.jsx
import { useEffect, useState } from "react";
function Users() {
const [users, setUsers] = useState([]);
useEffect(() => {
const controller = new AbortController();
fetch("/api/users", { signal: controller.signal })
.then((res) => res.json())
.then(setUsers)
.catch((err) => {
if (err.name !== "AbortError") console.error(err);
});
return () => controller.abort();
}, []);
return <ul>{users.map((u) => <li key={u.id}>{u.name}</li>)}</ul>;
}
O array de dependências controla quando o efeito é executado novamente: um array vazio executa apenas uma vez após a montagem, uma lista de valores executa quando qualquer um deles for alterado, e a ausência de um array executa após cada renderização. A função retornada é a de cleanup, que é executada antes do próximo efeito e na desmontagem do componente. Sempre faça o cleanup de subscriptions e requisições em andamento.
Context e refs
Context compartilha um valor com toda uma subárvore sem a necessidade de prop drilling.
// theme.jsx
const ThemeContext = createContext("light");
function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
function Button() {
const theme = useContext(ThemeContext);
return <button className={theme}>Click</button>;
}
Refs guardam um valor mutável ou um nó do DOM que não deve disparar uma nova renderização.
// focus.jsx
const inputRef = useRef(null);
useEffect(() => inputRef.current?.focus(), []);
return <input ref={inputRef} />;
Fluxo de dados e lifting state
O fluxo de dados no React ocorre em uma única direção. Quando dois componentes irmãos precisam compartilhar um estado, você faz o lift (elevação) desse estado para o pai comum mais próximo, passando o valor para baixo como uma prop e a função de atualização como um callback. Isso mantém uma única fonte da verdade e torna o fluxo de alterações fácil de acompanhar.
Para árvores de componentes mais profundas, o uso de context ou de uma biblioteca de estado dedicada, como Zustand ou Redux, pode valer a pena. Utilize essas ferramentas quando a passagem de props se tornar dolorosa, e não antes.
Hooks e custom hooks
Hooks são funções que permitem que os componentes utilizem funcionalidades do React. Eles devem ser chamados no nível superior, nunca dentro de condicionais ou loops. Assim que você os compreender, poderá extrair a lógica compartilhada para um custom hook.
// useFetch.js
function useFetch(url) {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
useEffect(() => {
let active = true;
fetch(url)
.then((res) => res.json())
.then((json) => active && setData(json))
.catch((err) => active && setError(err));
return () => { active = false; };
}, [url]);
return { data, error };
}
Um custom hook é apenas uma função cujo nome começa com use e que chama outros hooks. Ele compartilha a lógica, não o estado — cada componente que o utiliza recebe sua própria cópia independente.
Melhores práticas
- Mantenha os componentes pequenos e focados em apenas uma responsabilidade.
- Calcule valores derivados durante a renderização em vez de armazená-los no state.
- Use a forma de atualização (updater form) de um setter quando o próximo valor depender do anterior.
- Atribua a cada item de uma lista uma key estável proveniente dos seus dados.
- Faça a limpeza (cleanup) de effects, especialmente de subscriptions e requisições pendentes.
- Eleve o state (lift state) apenas até onde for necessário.
- Extraia lógicas repetidas para custom hooks.
- Recorra à memoização (
useMemo,useCallback,memo) apenas após medir e identificar um problema real.
Erros comuns
- Mutar o estado diretamente em vez de criar um novo valor.
- Usar o índice do array como key, quebrando a reordenação.
- Colocar dados derivados no estado e sincronizá-los com um effect.
- Esquecer o array de dependências e causar loops infinitos.
- Chamar um hook condicionalmente, quebrando as regras dos hooks.
- Otimizar com memoização antes de existir um problema de performance.
Próximos passos
O React é a camada de visualização; o Next.js adiciona roteamento, busca de dados e renderização no servidor sobre ele. Compare esse modelo com Vue e Svelte, e fortaleça seus fundamentos com JavaScript e TypeScript. O tutorial interativo de React apresenta essas mesmas ideias passo a passo.