Desenvolvimento de aplicações modernas com React
Guia completo para criar aplicações web performáticas e de fácil manutenção com React.
InSkillCoach
Desenvolvimento de aplicações modernas com React
React é uma das bibliotecas JavaScript mais populares para a criação de interfaces de usuário. Desenvolvida e mantida pelo Facebook (Meta), ela permite construir aplicações web complexas com componentes reutilizáveis e um gerenciamento eficiente de estado.
Por que escolher o React?
- Abordagem declarativa: Você descreve como a UI deve ficar, e o React cuida das atualizações
- Baseado em componentes: Crie elementos de interface encapsulados e reutilizáveis
- Ecossistema rico: Uma ampla variedade de bibliotecas e ferramentas complementares
- Grande comunidade: Suporte, recursos e atualizações regulares
- Desempenho otimizado: Virtual DOM e reconciliação para atualizações eficientes
- Adotado por grandes empresas: Facebook, Instagram, Netflix, Airbnb etc.
Configurando um projeto React
Criação com Create React App
O Create React App é uma ferramenta oficial que permite iniciar rapidamente um projeto React:
# Instalação
npx create-react-app mon-application
# Inicialização
cd mon-application
npm start
Usando o Vite (alternativa moderna)
O Vite oferece tempos de compilação mais rápidos e uma melhor experiência de desenvolvimento:
# Instalação
npm create vite@latest mon-application -- --template react
# Inicialização
cd mon-application
npm install
npm run dev
Os fundamentos do React
Componentes
Os componentes são os blocos de construção básicos de uma aplicação React:
// Componente funcional
function Salutation(props) {
return <h1>Bonjour, {props.nom} !</h1>;
}
// Utilização
<Salutation nom="Alice" />
JSX
JSX é uma extensão de sintaxe que permite escrever HTML dentro do JavaScript:
const element = <h1>Bonjour, monde !</h1>;
// Com expressões JavaScript
const nom = "Alice";
const element = <h1>Bonjour, {nom} !</h1>;
// Com atributos
const element = <img src={user.avatarUrl} alt="Avatar" />;
// Elementos aninhados
const element = (
<div>
<h1>Titre</h1>
<p>Paragraphe</p>
</div>
);
Props
As props permitem passar dados de um componente pai para um componente filho:
// Definição do componente
function Carte(props) {
return (
<div className="carte">
<h2>{props.titre}</h2>
<p>{props.description}</p>
{props.children}
</div>
);
}
// Utilização
<Carte
titre="Mon titre"
description="Ma description"
>
<button>En savoir plus</button>
</Carte>
Estado (State)
O estado permite armazenar dados que podem mudar ao longo do tempo:
import { useState } from 'react';
function Compteur() {
// Declaração de um estado
const [compteur, setCompteur] = useState(0);
return (
<div>
<p>Vous avez cliqué {compteur} fois</p>
<button onClick={() => setCompteur(compteur + 1)}>
Cliquez ici
</button>
</div>
);
}
Ciclo de vida com Hooks
Os Hooks permitem usar o estado e outros recursos do React em componentes funcionais:
import { useState, useEffect } from 'react';
function ExempleEffet() {
const [compteur, setCompteur] = useState(0);
// Semelhante a componentDidMount e componentDidUpdate
useEffect(() => {
// Atualiza o título do documento
document.title = `Vous avez cliqué ${compteur} fois`;
// Função de limpeza (semelhante a componentWillUnmount)
return () => {
document.title = 'React App';
};
}, [compteur]); // Executa apenas se compteur mudar
return (
<div>
<p>Vous avez cliqué {compteur} fois</p>
<button onClick={() => setCompteur(compteur + 1)}>
Cliquez ici
</button>
</div>
);
}
Tratamento de eventos
O React usa uma sintaxe semelhante à do HTML para tratar eventos:
function Bouton() {
function handleClick(e) {
e.preventDefault();
console.log('Le bouton a été cliqué');
}
return (
<button onClick={handleClick}>
Cliquez ici
</button>
);
}
Renderização condicional
Você pode exibir diferentes elementos em função de condições:
function Connexion(props) {
const estConnecte = props.estConnecte;
return (
<div>
{estConnecte ? (
<BoutonDeconnexion />
) : (
<BoutonConnexion />
)}
</div>
);
}
// Outra abordagem
function Message(props) {
const nonLu = props.messagesNonLus.length;
return (
<div>
<h1>Bonjour !</h1>
{nonLu > 0 && (
<p>Vous avez {nonLu} message(s) non lu(s).</p>
)}
</div>
);
}
Listas e chaves
Para exibir listas de elementos, use map() e chaves únicas:
function ListeArticles(props) {
const articles = props.articles;
return (
<ul>
{articles.map((article) => (
<li key={article.id}>
{article.titre}
</li>
))}
</ul>
);
}
Gerenciamento avançado de estado
Context API
A Context API permite compartilhar dados entre componentes sem passar pelas props:
// Criação do contexto
const ThemeContext = React.createContext('light');
// Provedor de contexto
function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
// Consumo do contexto com useContext
function Bouton() {
const theme = useContext(ThemeContext);
return (
<button className={theme}>
Je suis stylisé selon le thème {theme}
</button>
);
}
useReducer para um gerenciamento de estado complexo
useReducer é preferível a useState para estados complexos:
import { useReducer } from 'react';
// Definição do reducer
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { compteur: state.compteur + 1 };
case 'decrement':
return { compteur: state.compteur - 1 };
default:
throw new Error();
}
}
function Compteur() {
// Utilização do reducer
const [state, dispatch] = useReducer(reducer, { compteur: 0 });
return (
<div>
Compteur: {state.compteur}
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</div>
);
}
Bibliotecas de gerenciamento de estado
Para aplicações mais complexas, você pode usar bibliotecas dedicadas:
Redux
// Actions
const INCREMENT = 'INCREMENT';
const DECREMENT = 'DECREMENT';
// Action creators
function increment() {
return { type: INCREMENT };
}
// Reducer
function compteurReducer(state = { valeur: 0 }, action) {
switch (action.type) {
case INCREMENT:
return { valeur: state.valeur + 1 };
case DECREMENT:
return { valeur: state.valeur - 1 };
default:
return state;
}
}
// Store
const store = createStore(compteurReducer);
// Componente conectado
function Compteur({ valeur, increment, decrement }) {
return (
<div>
<span>{valeur}</span>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</div>
);
}
const mapStateToProps = state => ({
valeur: state.valeur
});
const mapDispatchToProps = {
increment,
decrement
};
export default connect(mapStateToProps, mapDispatchToProps)(Compteur);
Zustand (alternativa moderna)
import create from 'zustand';
// Criação do store
const useStore = create(set => ({
compteur: 0,
increment: () => set(state => ({ compteur: state.compteur + 1 })),
decrement: () => set(state => ({ compteur: state.compteur - 1 })),
}));
// Utilização em um componente
function Compteur() {
const { compteur, increment, decrement } = useStore();
return (
<div>
<span>{compteur}</span>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</div>
);
}
Roteamento com React Router
O React Router permite gerenciar a navegação em uma aplicação React:
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
function App() {
return (
<BrowserRouter>
<nav>
<Link to="/">Accueil</Link>
<Link to="/a-propos">À propos</Link>
<Link to="/contact">Contact</Link>
</nav>
<Routes>
<Route path="/" element={<Accueil />} />
<Route path="/a-propos" element={<APropos />} />
<Route path="/contact" element={<Contact />} />
<Route path="/produits/:id" element={<DetailProduit />} />
<Route path="*" element={<PageNonTrouvee />} />
</Routes>
</BrowserRouter>
);
}
// Acesso aos parâmetros de URL
import { useParams } from 'react-router-dom';
function DetailProduit() {
const { id } = useParams();
return <h1>Détail du produit {id}</h1>;
}
Formulários no React
Formulários controlados
Em um formulário controlado, o React gerencia o estado do formulário:
import { useState } from 'react';
function FormulaireConnexion() {
const [email, setEmail] = useState('');
const [motDePasse, setMotDePasse] = useState('');
function handleSubmit(e) {
e.preventDefault();
console.log('Email:', email);
console.log('Mot de passe:', motDePasse);
}
return (
<form onSubmit={handleSubmit}>
<div>
<label>
Email:
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
</label>
</div>
<div>
<label>
Mot de passe:
<input
type="password"
value={motDePasse}
onChange={(e) => setMotDePasse(e.target.value)}
required
/>
</label>
</div>
<button type="submit">Se connecter</button>
</form>
);
}
Bibliotecas de formulários
Para formulários complexos, use bibliotecas como Formik ou React Hook Form:
// Com React Hook Form
import { useForm } from 'react-hook-form';
function FormulaireInscription() {
const { register, handleSubmit, formState: { errors } } = useForm();
const onSubmit = data => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label>Nom</label>
<input {...register('nom', { required: 'Le nom est requis' })} />
{errors.nom && <p>{errors.nom.message}</p>}
</div>
<div>
<label>Email</label>
<input
{...register('email', {
required: 'L\'email est requis',
pattern: {
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
message: 'Adresse email invalide'
}
})}
/>
{errors.email && <p>{errors.email.message}</p>}
</div>
<button type="submit">S'inscrire</button>
</form>
);
}
Otimização de desempenho
React.memo
React.memo permite evitar renderizações desnecessárias de componentes funcionais:
const MonComposant = React.memo(function MonComposant(props) {
// Seu componente
});
useMemo e useCallback
Esses hooks permitem memorizar valores e funções:
import { useMemo, useCallback } from 'react';
function ExempleOptimisation({ a, b }) {
// Memoriza o resultado do cálculo
const resultat = useMemo(() => {
console.log('Calcul coûteux...');
return a * b;
}, [a, b]); // Recalcula apenas se a ou b mudar
// Memoriza a função
const handleClick = useCallback(() => {
console.log('Bouton cliqué avec résultat:', resultat);
}, [resultat]); // Recria apenas se resultat mudar
return (
<div>
<p>Résultat: {resultat}</p>
<button onClick={handleClick}>Cliquer</button>
</div>
);
}
Lazy Loading
O carregamento sob demanda (lazy loading) permite dividir sua aplicação em partes menores:
import { lazy, Suspense } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
// Carregamento sob demanda dos componentes
const Accueil = lazy(() => import('./pages/Accueil'));
const APropos = lazy(() => import('./pages/APropos'));
const Contact = lazy(() => import('./pages/Contact'));
function App() {
return (
<BrowserRouter>
<Suspense fallback={<div>Chargement...</div>}>
<Routes>
<Route path="/" element={<Accueil />} />
<Route path="/a-propos" element={<APropos />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</Suspense>
</BrowserRouter>
);
}
Testes no React
Testes unitários com Jest e React Testing Library
// Componente a ser testado
function Salutation({ nom }) {
return <h1>Bonjour, {nom} !</h1>;
}
// Teste
import { render, screen } from '@testing-library/react';
import Salutation from './Salutation';
test('affiche le message de salutation', () => {
render(<Salutation nom="Alice" />);
const element = screen.getByText(/bonjour, alice !/i);
expect(element).toBeInTheDocument();
});
Testes de interação
import { render, screen, fireEvent } from '@testing-library/react';
import Compteur from './Compteur';
test('incrémente le compteur lorsque le bouton est cliqué', () => {
render(<Compteur />);
// Verificar o valor inicial
expect(screen.getByText(/compteur: 0/i)).toBeInTheDocument();
// Clicar no botão
fireEvent.click(screen.getByText('+'));
// Verificar o novo valor
expect(screen.getByText(/compteur: 1/i)).toBeInTheDocument();
});
Deploy de uma aplicação React
Build de produção
# Com Create React App
npm run build
# Com Vite
npm run build
Hospedagem estática
Você pode fazer o deploy da sua aplicação em plataformas como:
- Netlify: Arraste e solte a pasta
buildou configure um deploy contínuo - Vercel: Otimizada para aplicações React, com deploy automático a partir do GitHub
- GitHub Pages: Ideal para projetos pessoais ou open source
- Firebase Hosting: Solução completa com autenticação e banco de dados
Boas práticas
- Estruture seu projeto: Organize seus arquivos por funcionalidade ou tipo
- Use componentes funcionais: Mais simples e mais performáticos com Hooks
- Evite o props drilling: Use Context ou uma biblioteca de gerenciamento de estado
- Escreva testes: Garanta que sua aplicação funcione como esperado
- Otimize o desempenho: Use React.memo, useMemo e useCallback com critério
- Siga os princípios SOLID: Crie componentes com responsabilidade única
- Use TypeScript: Adicione tipagem estática para evitar erros
- Documente seus componentes: Use ferramentas como o Storybook
Conclusão
React é uma biblioteca poderosa que permite criar interfaces de usuário modernas e de alto desempenho. Sua flexibilidade e seu rico ecossistema fazem dela uma excelente escolha para o desenvolvimento de aplicações web de todos os tamanhos.
Ao dominar os conceitos fundamentais e as boas práticas apresentados neste artigo, você será capaz de criar aplicações React robustas, de fácil manutenção e escaláveis.
Sobre InSkillCoach
Especialista em treinamento e tecnologias
Coach especializado em tecnologias avançadas e IA, apoiado pela GNeurone Inc.
Certificações:
- AWS Certified Solutions Architect – Professional
- Certificações Google Cloud
- Microsoft Certified: DevOps Engineer Expert
- Certified Kubernetes Administrator (CKA)
- CompTIA Security+
Comentários
Os comentários são alimentados pelo GitHub Discussions
Conecte-se com o GitHub para participar da discussão