Alura > Cursos de Front-end > Cursos de React > Conteúdos de React > Primeiras aulas do curso React: aprenda a pensar em componentes

React: aprenda a pensar em componentes

Seu primeiro componente react - Apresentação

Apresentando o curso e objetivos iniciais

Olá! Seja muito bem-vinde a este curso. Meu nome é Vinícius Neves, o calvo barbudo que virou seu melhor amigo desde ontem.

Desta vez, nós vamos falar sobre React, em continuação direta ao nosso curso sobre JavaScript, DOM, eventos e requisições. Nós vamos pegar o projeto Focus, que implementamos manualmente com JavaScript Vanilla (puro), e migrá-lo para React.

Explorando a migração do projeto e ferramentas

Ao abrirmos o projeto no VS Code, nós veremos toda a estrutura de componentes, os hooks (ganchos) do React, as regras do React e os motivos de o React existir. Nós passaremos por uma jornada muito interessante.

Qual é a vantagem? Como já estaremos trabalhando com um projeto com o qual nós temos familiaridade, o próprio Focus, nós entenderemos melhor as diferenças entre as abordagens, formaremos opiniões e identificaremos o que é mais simples em cada caso.

Além de migrar, nós também abordaremos o essencial de TypeScript. Para quê? Para que possamos falar a linguagem do mercado, porque hoje, normalmente, na maioria das vagas, a dupla inseparável é React com TypeScript.

Detalhando os conteúdos do curso de React

Nós vamos aprender muitas coisas.

Neste curso, nós vamos aprender React em si: por que existe, o que é JSX, quais regras devemos seguir ao usar React, como pensar em componentes e quais cuidados adotar para escrever um código que não apenas funcione, mas que esteja pronto para escalar, sobreviver ao tempo e receber novas funcionalidades.

Nós vamos analisar recursos específicos do React 19 e entender como eram no React 18 e em versões anteriores. Há muitos tópicos interessantes que exploraremos ao longo das aulas.

Explicando a metodologia e pré-requisitos

Não se trata apenas de colocar a mão na massa nem de pedir para agentes resolverem tudo. Nós vamos discutir quais métricas utilizamos e, após dominarmos e entendermos como algo funciona, passaremos a trabalhar bastante com agentes de código.

O pré-requisito é o curso anterior. Se você já entende como JavaScript funciona no navegador, está plenamente preparade para começar o curso de React.

Apresentando a estrutura do curso e encerramento

Este curso tem duas partes. Primeiro, construiremos um grande hello world (olá, mundo) para entender como funciona o ecossistema do React. No segundo curso, nós vamos nos aprofundar em conteúdos mais avançados, com práticas adotadas no mercado.

Em resumo, são duas etapas: primeiro, vamos entender React e suas regras; depois, vamos escalar o que aprendermos.

Eu espero que você esteja tão entusiasmade quanto eu. Eu prometo que não vou sair daqui. Te espero no próximo vídeo. Vamos.

Seu primeiro componente react - Criando o projeto com Vite + React

Apresentando o curso e as ferramentas

Vamos colocar a mão na massa. Neste curso, nós vamos desenvolver o Focus novamente, agora usando React.

Quais ferramentas vamos precisar para acompanhar?

Nós vamos usar o Cloud Code desta vez. Para evitarmos ficar sem créditos, vamos usar o Cloud Code com esse objetivo. Como ele é pago, será necessário fazer a assinatura; no entanto, há alternativas que funcionam com o mesmo mecanismo e com o mesmo fluxo de prompt. Entre elas, estão o GitHub Copilot, o próprio Cursor do curso anterior e o Anti-Gravity. Se não quisermos assinar ali, isto é, se não quisermos fazer a assinatura da Anthropic, outra alternativa paga é o OpenAI Codex. Se já houver uma assinatura da OpenAI, podemos usar o Codex. O funcionamento é o mesmo: são ferramentas diferentes, mas o mecanismo de uso é equivalente.

Podemos pensar nisso como uma aula de direção: cada pessoa escolhe o carro que vai dirigir. Não precisa ser o mesmo carro, porque o mecanismo é o mesmo — volante, alavanca de câmbio, acelerar, frear, embreagem. A ferramenta, neste caso, é o de menos. Escolhemos a que mais agradar, com a qual houver mais familiaridade ou a que já utilizamos no dia a dia.

Configurando o projeto React com Vite

Como vamos criar um projeto em React, precisaremos do Vite. Já aprendemos o que é o Vite e como ele funciona no curso anterior. Vamos direto ao terminal.

No terminal, verificamos se há alguma pasta. Perfeito: o que temos na "Área de Trabalho" é o projeto final do curso anterior. Vamos aproveitar partes dele para facilitar nosso trabalho.

Para checar o conteúdo da pasta atual no terminal, podemos listar os arquivos com:

ls

Agora vamos criar o projeto em React. Já temos um projeto em JavaScript para WebFocus; vamos pedir ao npm que crie outra aplicação com o Vite.

Para iniciar o assistente do Vite, execute:

npm create vite@latest

O create-vite solicitou atualização para a versão 9.1.1; autorizamos a instalação. O nome do projeto será "React-Focus". Em seguida, escolhemos o framework (estrutura): desta vez, não será Vanilla; queremos usar React. Depois, selecionamos a variante: JavaScript com React Compiler.

Quando o assistente pedir o nome do projeto, informe, por exemplo:

react-fokus

Neste momento, o assistente lista diversas formas de trabalhar com React: aparecem opções como React Server Components (que usa um plugin (complemento) do Vite), React Router, TanStack Router, RedwoodJS e Vite, entre outras. Vamos seguir com React com React Compiler. Nós vamos deixar uma atividade em texto explicando o que é o React Compiler, para não entrarmos agora em conteúdo excessivamente teórico. De forma direta, o React Compiler faz exatamente o que o nome indica: compila, isto é, transforma o código que escrevemos em outra coisa. Ele fará essa compilação, essa transformação do que escrevemos para outra forma. Não precisamos nos preocupar com isso neste momento.

O linter (verificador estático) é uma ferramenta que analisa nosso código em busca de erros enquanto ainda estamos escrevendo. Nós vamos usar o ESLint, que já utilizamos há bastante tempo.

Ao final, o assistente pergunta se queremos fazer um install (instalação) e um start (inicialização). Respondemos que sim para ambos. O processo fará exatamente o que já vimos anteriormente. Desta vez, pode demorar um pouco mais, porque uma aplicação Vanilla tem praticamente nenhuma dependência, enquanto React traz as suas; vêm muitos pacotes por padrão como dependências.

Ao terminar, a aplicação abrirá em localhost:5173. Abrimos a página e ela traz bastante conteúdo: há um contador que exibe o valor atual e, conforme clicamos, ele incrementa. Há também bastante documentação, citando a comunidade do Vite no GitHub, no Discord, no X e no Bluesky, além de documentação do próprio Vite e do React. Quando iniciamos uma aplicação do zero com React usando o Vite, esse projeto de exemplo é incluído.

Abrindo o projeto na IDE e explorando a estrutura

O que vamos fazer agora na nossa IDE (ou editor de código)? Vamos abrir outra aba do terminal e abrir o VS Code nessa pasta. Observamos que abrimos por engano na "Área de Trabalho"; não é o que queremos. Queremos entrar na pasta "React-Focus".

Primeiro, abrimos o VS Code na pasta atual:

code .

Como abrimos no diretório errado, navegamos para a pasta do projeto e abrimos novamente o editor:

cd react-fokus/
code .

Agora sim, vamos abrir o VS Code na pasta "ReactFocus". Vamos ajustar o zoom e fechar o Copilot. Aqui está toda a aplicação que foi gerada para nós.

Ao explorar a pasta "src", encontramos o arquivo main.jsx (observe a extensão). Nele, vemos createRoot, StrictMode e App. Com o tempo, entenderemos esses elementos. Em index.css, temos um CSS global. O App.jsx é o que já estamos vendo no navegador: traz o “Get started”, orienta a editar, inclui o botão que incrementa o contador, as seções de documentação do Vite (Vite) e do React (React), e a parte de comunidade. Ou seja, esse App.jsx é o código que montou a tela que vimos no Chrome.

Para conectar a aplicação ao ponto de entrada do HTML, o main.jsx gerado pelo Vite/React usa createRoot, envolve a aplicação em StrictMode e importa os estilos globais. Ele se parece com isto:

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'

createRoot(document.getElementById('root')).render(
  <StrictMode>
    <App />
  </StrictMode>,
)

Limpando o scaffold e preparando o App

O que vamos fazer agora? Vamos limpar tudo e deixar o projeto preparado para começarmos o Focus. De baixo para cima, não precisamos alterar nada em main.jsx. No index.css, há muitas definições de cor, media queries (consultas de mídia) e outras regras; podemos remover esse conteúdo. Em app.css, que é o CSS relacionado ao App.jsx, também podemos remover as regras. Não vamos apagar o arquivo; apenas vamos limpar o CSS. O mecanismo de recarregamento é o mesmo do vanilla (JavaScript puro) e já exibe a aplicação aqui sem qualquer estilo — apenas a marcação HTML.

No App.jsx, dentro do return, vamos apagar tudo e deixar somente o return entre parênteses. Também vamos remover todas as importações, de modo que fique apenas o App. A linha 2 com useState também será removida.

Após limpar o conteúdo JSX do return, o componente ainda pode estar com o estado importado e sem markup. Algo assim:

import { useState } from 'react'

function App() {
  const [count, setCount] = useState(0)

  return (
    
  )
}

export default App

Em seguida, removemos as importações que não vamos usar e também a linha do useState, deixando apenas a função do componente com um return vazio:

function App() {

  return (
    
  )
}

export default App

Agora, vamos decidir o que retornar aqui: um h1 com o texto Focus. Primeiro, adicionamos a tag h1:

function App() {

  return (
    <h1></h1>
  )
}

export default App

Por fim, adicionamos o texto dentro do h1. No meu código de exemplo, o título aparece como “Fokus”; se preferir alinhar exatamente ao que falamos na explicação, você pode usar “Focus”.

function App() {

  return (
    <h1>Fokus</h1>
  )
}

export default App

Ao voltar ao navegador, o resultado é exibido. Se inspecionarmos o elemento e selecionarmos o h1 com “Focus”, veremos uma div com id="root" e, dentro dela, o h1 contendo “Focus”.

Analisando dependências e introduzindo o JSX

Temos algumas novidades. Além de o Vite (Vite) já preparar o projeto para React (React), adicionando novas dependências, podemos olhar o package.json: os scripts permanecem os mesmos, não mudou nada. Porém, nas dependências, temos o próprio React (React) — a parte com a qual escrevemos — e o React DOM (Modelo de Objeto do Documento do React), que é responsável por escrever isso no DOM (Modelo de Objeto do Documento) do navegador, algo que já manipulamos bastante.

Há também várias dependências de desenvolvimento: Babel (Babel) core, ESLint (ESLint) — com quatro dependências do ESLint —, um plugin (extensão) do Babel (Babel), os types (tipos) de React (React) e de React DOM (DOM do React), um plugin (extensão) do Vite (Vite) para React (React), o Babel plugin (extensão do Babel) do React Compiler, mais itens de ESLint (ESLint), uma dependência chamada Globals e outra chamada Vite (Vite), que é a ferramenta que utilizamos para montar nosso ambiente de desenvolvimento. Ou seja, já temos bastante coisa diferente.

Não vamos explicar em detalhes o que cada dependência faz. Podemos fazer uma busca no Google ou abrir o assistente de código e pedir essa explicação. Podemos selecionar as dependências de desenvolvimento, copiar e colar no chat, escolher o modelo (por exemplo, o Suite Model), ajustar o zoom se necessário apenas para selecionar o modelo padrão e, então, solicitar: “Explique o que cada uma dessas funcionalidades faz.” No nosso caso aqui, o assistente solicitou autenticação; não vamos iniciar sessão agora. Fica a sugestão para investigar e pedir ao assistente de código que explique cada item; não precisamos entrar nesse terreno neste momento.

Além disso, há um index.html com uma div id="root" vazia, e ele importa um arquivo jsx a partir de src/main. Ao final, está o código que escrevemos. Isso é relativamente diferente do Vite (Vite), e há algo novo nessa extensão .jsx — até agora, usávamos apenas .js. O return está retornando algo que se parece muito com HTML, porém dentro de uma função. Esse JSX mistura uma marcação semelhante a HTML com JavaScript (JavaScript).

Encerrando a configuração e antecipando os próximos tópicos

A base do projeto — nosso ponto de partida — está pronta. A partir daqui, vamos evoluir, saindo desse h1 até chegarmos à nossa aplicação completa em funcionamento.

Antes de começarmos a escrever código, vamos conversar sobre o que é React (React), o que é JSX, como funciona e tudo mais. Antes de continuar com nosso hands-on (prática), vamos nos aprofundar nessa biblioteca de frontend (interface de cliente) tão conhecida chamada React (React). Falaremos sobre isso no próximo vídeo.

Seu primeiro componente react - O que é jsx

Apresentando o JSX e sua relação com HTML e JavaScript

Vamos discutir o que é, afinal, o JSX e por que usamos essa extensão. Ao observarmos o código que escrevemos, colocamos um h1, escrevemos o texto Focus dentro e parece HTML. Foi o primeiro código que escrevemos em React. Ao olharmos a função, não há muito que já não tenhamos visto. A extensão é uma novidade: esse JSX é algo novo. A extensão do arquivo é nova para nós. Agora, uma função JavaScript nós reconhecemos. O nome da função começando com letra maiúscula normalmente não é um padrão em JavaScript, então isso também pode soar estranho. No final fazemos um retorno com return entre parênteses, porque precisaremos de múltiplas linhas, e dentro há algo que parece HTML. Há certa familiaridade, mas isso não é um arquivo *.html, é um arquivo *.jsx.

Para visualizar esse primeiro contato com JSX, veja a marcação simples que escrevemos (que se parece com HTML, mas é JSX dentro de um arquivo .jsx):

<h1>fokus</h1>

O HTML viverá em um arquivo *.html e, em geral, é um documento. Existem algumas variações, mas, de forma geral, o HTML vive dentro de um arquivo *.html. Esse documento manipulamos via API do DOM, como já aprendemos no curso anterior. O JSX viverá dentro de uma função JavaScript, exatamente dentro do retorno da função. Se voltarmos ao exemplo, onde está o JSX? Está dentro do return. O JSX é essa marcação: h1 com o texto Focus. Portanto, essa marcação que parece HTML, escrita dentro de JavaScript, dentro de uma função JavaScript, é o JSX.

Para deixar isso claro no contexto de um componente, veja como o JSX aparece dentro do return de uma função em um arquivo .jsx:

// App.jsx

function App() {
  return (
    <h1>fokus</h1>
  )
}

Vamos recorrer à documentação oficial do React para entender do que estamos falando. Extraímos, em tradução livre, uma explicação direta da documentação do React que diz o seguinte: o JSX é uma extensão de sintaxe, isto é, estende a sintaxe do JavaScript, permitindo escrever marcação parecida com HTML dentro de um arquivo JavaScript. O ponto central é: é uma extensão de sintaxe e se parece com HTML.

Explicando a tradução do JSX para React.createElement

Quando escrevemos um h1 com o texto Focus, repare que há inclusive um className. O className corresponde ao class, a classe CSS. O que o React está vendo, na verdade, é uma função; dentro do React existe uma função chamada createElement que recebe vários parâmetros. Primeiro, qual é o elemento HTML que estamos criando? No exemplo, o elemento é h1. Depois, recebe um objeto de configuração. Por exemplo, passamos className com o valor "title", uma classe CSS — vamos abordar o className em seguida. E, por fim, o conteúdo em si, que é uma cadeia de caracteres, o texto "Focus". Assim, o que vemos é a marcação, e o que o React enxerga, por baixo dos panos, é uma forma de criar um elemento.

Para ilustrar o que escrevemos e o que o React interpreta por baixo dos panos:

// o que você escreve:
<h1 className="title">fokus</h1>
// o que o react vê:
React.createElement('h1', { className: 'title' }, 'fokus')

E se tivermos vários elementos aninhados? Suponhamos um div contendo um h1 com Focus e um p com PomodoroApp. Como o React entende isso? De forma aninhada. Um div vazio, sem className, sem nada, tem o segundo parâmetro nulo, ou seja, não possui nenhuma configuração, e cria um div. O terceiro parâmetro é o conteúdo. A partir daí, podemos encadear: o terceiro parâmetro é o conteúdo, incluindo um h1, e, ao lado, passamos outro elemento, o parágrafo, com o texto PomodoroApp. Podemos fazer isso para vários elementos. O React vai separando por vírgulas e passando os elementos; enquanto existirem, o React os renderizará. Esse processo é encadeado, isto é, recursivo. Cada componente, cada trecho de JSX encontrado, é transformado em algo muito parecido com essa estrutura de chamadas.

Veja o JSX aninhado e sua forma equivalente com React.createElement:

// jsx:
<div>
  <h1>fokus</h1>
  <p>pomodoro app</p>
</div>
// o que vira:
React.createElement('div', null,
  React.createElement('h1', null, 'fokus'),
  React.createElement('p', null, 'pomodoro app')
)

Esclarecendo as regras do JSX e o uso de className

Ao falarmos de JSX, precisamos seguir as regras do JSX. O HTML tem suas próprias regras. O JSX parece HTML, mas não é HTML. O HTML tem as regras do próprio HTML; o JavaScript tem as regras do próprio JavaScript; e o JSX estende a sintaxe do JavaScript. Portanto, se houver alguma discrepância entre JSX e JavaScript, o JavaScript sempre prevalecerá. JavaScript vence ao final em caso de conflito.

O primeiro ponto que vamos tratar, que já vimos rapidamente antes, é o className.

Em HTML escrevemos div com o atributo class, definindo a classe desejada. Em JSX usamos className. Por que usamos className e não class? class é uma palavra reservada em JavaScript. No VS Code, dentro do JSX, ao digitar class — por exemplo, em algo como classCalculadora — a sintaxe evidencia isso (a cor muda) porque é uma palavra reservada. Portanto, não podemos usar essa palavra reservada. E, como já mencionamos, quando há discrepância, JavaScript prevalece. Assim, não podemos usar class; precisamos usar className. No restante, o funcionamento é igual: class tornou-se className.

Para comparar diretamente, observe o mesmo trecho em HTML puro e em JSX:

<!-- html -->
<div class="timer-card">
// jsx
<div className="timer-card">

Inserindo JavaScript no JSX e diferenciando expressões de declarações

Podemos inserir JavaScript dentro do JSX. Por exemplo, temos valores como o modo foco e o tempo, que pode ser 1500 segundos. Vamos colocar a variável modo entre chaves no elemento h2: o React pegará a cadeia e a imprimirá para nós na tela. Também podemos combinar operações; por exemplo, podemos pegar o tempo e dividir por 60. Esse tempo dividido por 60 nos dará a quantidade de horas, e Math.floor fará o arredondamento. Se tivermos 1.5 horas, queremos apenas 1; se tivermos 2, queremos apenas 2. Assim, sempre arredondaremos para obter a quantidade de horas inteiras que se passaram. Podemos fazer essas instruções dentro do JSX. Se quisermos converter algo para maiúsculas, podemos pegar nossa variável focus e chamar .toUpperCase(): JavaScript funcionará. Dessa forma, podemos combinar ambas as coisas, porque o JSX, no fim das contas, é uma forma de renderizar elementos na tela.

Veja um exemplo prático dessas inserções de JavaScript dentro do JSX:

const modo = 'foco'
const tempo = 1500

<h2>{modo}</h2>
<span>{Math.floor(tempo / 60)}:00</span>
<p>{'fokus'.toUpperCase()}</p>

O que funciona no JSX? Expressões. O primeiro exemplo é um operador ternário: se o modo é foco, imprimimos 25 minutos; caso contrário, imprimimos 5 minutos. tarefas.length, que é o tamanho da nossa lista de tarefas, também funciona. .toUpperCase(), visto no exemplo anterior, também funciona.

Para reforçar, aqui estão exemplos de expressões que funcionam:

// funciona (expressões):
{modo === 'foco' ? '25:00' : '05:00'}
{tarefas.length}
{nome.toUpperCase()}

O que não funciona? Nada que seja uma declaração. Não podemos colocar um if ou um for dentro do JSX; o JSX não foi projetado para isso. Portanto, expressões funcionam; declarações, não.

Eis exemplos de declarações que não funcionam dentro das chaves do JSX:

// não funciona (declarações):
{if (modo === 'foco') { ... }}
{for (let i = 0; i < 10; i++) { ... }}

Refatorando lógica para legibilidade e reutilização no JSX

Entretanto, o fato de algo funcionar não significa que vamos colocar tudo ali dentro. Podemos fazer muitas coisas dentro do JSX, mas será essa a melhor solução? Vejamos um exemplo que já vimos: usar .toLocaleTimeString() para formatar hora e minuto, extraindo quantos minutos e segundos há. Como sempre falamos de menos de uma hora, isso sempre funcionará. Pegamos a quantidade de segundos, multiplicamos por mil, instanciamos um new Date() e chamamos .toLocaleTimeString(), passando 'pt-BR' e as opções: minuto com dois dígitos e segundo com dois dígitos. Nesse cenário, recebemos um parâmetro chamado segundos, usamos para instanciar o novo objeto Date e chamamos .toLocaleTimeString().

Para começar, podemos fazer tudo diretamente dentro do JSX:

function TimerDisplay({ segundos }) {
  return (
    <span className="timer-card__time">
      {new Date(segundos * 1000).toLocaleTimeString('pt-BR', {
        minute: '2-digit',
        second: '2-digit',
      })}
    </span>
  )
}

Se quisermos tornar isso mais legível, podemos extrair a lógica e colocá-la antes do return. Pegamos o tempo, fazemos toda essa lógica fora do JSX e, ao final, apenas o imprimimos. Fica mais fácil de ler.

Veja a mesma ideia com a variável tempo calculada antes:

function TimerDisplay({ segundos }) {
  const tempo = new Date(segundos * 1000).toLocaleTimeString('pt-BR', {
    minute: '2-digit',
    second: '2-digit',
  })

  return (
    <span className="timer-card__time">
      {tempo}
    </span>
  )
}

Se quisermos algo ainda melhor e reutilizável, podemos criar uma função chamada formatarTempo, uma função JavaScript pura que recebe a quantidade de segundos e devolve no formato que queremos. No nosso componente, chamamos essa função passando a quantidade de segundos: formatarTempo com esses segundos. A funcionalidade é a mesma; as três versões fazem o mesmo. Qual é o ponto? A legibilidade conta.

Aqui está a extração para uma função utilitária reutilizável:

// função separada, testável, reutilizável
function formatarTempo(segundos) {
  return new Date(segundos * 1000).toLocaleTimeString('pt-BR', {
    minute: '2-digit',
    second: '2-digit',
  })
}

function TimerDisplay({ segundos }) {
  return (
    <span className="timer-card__time">
      {formatarTempo(segundos)}
    </span>
  )
}

Quando colocamos algo dentro do JSX? Quando for algo mais simples: inserir diretamente uma variável, imprimir o resultado de uma função ou aplicar uma lógica muito curta. Se a lógica for mais complexa ou se repetir, não faz sentido colocá-la no JSX. O fato de algo funcionar não significa que devemos fazer. Uma coisa é funcionar; outra é seguirmos boas práticas do mercado.

Sobre o curso React: aprenda a pensar em componentes

O curso React: aprenda a pensar em componentes possui 328 minutos de vídeos, em um total de 69 atividades. Gostou? Conheça nossos outros cursos de React em Front-end, ou leia nossos artigos de Front-end.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda React acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas