Alura > Cursos de Front-end > Cursos de React > Conteúdos de React > Primeiras aulas do curso React: construa uma aplicação front-end completa

React: construa uma aplicação front-end completa

Explorando o React Router - Apresentação

Apresentando a continuação do curso

Olá, bem-vindas e bem-vindos! Eu continuo sendo o Careca Barbudo, sua pessoa amiga. Este curso é uma continuação direta do curso no qual desenvolvemos o aplicativo de Pomodoro, Focus.

Agora, vamos deixar esse aplicativo de lado e utilizar outra aplicação. Nós vamos desenvolver uma rede social para pessoas que gostam de correr.

Definindo objetivos técnicos iniciais

Para chegar a esse resultado, precisaremos lidar com o início de sessão de pessoas usuárias, isto é, login (início de sessão) e cadastro. Precisaremos cadastrar pessoas usuárias e iniciar suas sessões.

Também teremos comunicação com o back-end (camada de servidor): como nos comunicamos com o back-end dentro do ecossistema do React, qual é a abordagem antiga, qual é a abordagem nova, quando utilizar cada uma e qual estilo adotar em cada momento.

Detalhando funcionalidades da aplicação

Nós poderemos adicionar comentários; o recurso de comentários estará disponível, o que nos permitirá interagir com todas as publicações. Teremos várias páginas para navegação, incluindo uma página de perfil, e enviaremos imagens.

Há diversas funcionalidades interessantes para consolidar e ampliar nosso conjunto de ferramentas do ecossistema do React.

Preparando o projeto base e convidando para o próximo vídeo

Para chegar lá, partiremos de um projeto base que já tem todo o layout (estrutura visual) pronto, mas sem comportamento, e nós o evoluiremos. Aprenderemos como fazer a navegação e como nos comunicamos com o back-end (camada de servidor). E, falando em back-end, colocaremos um back-end do zero. Não vamos construí-lo; nós o receberemos pronto da equipe de back-end, mas aprenderemos a ler documentação e a colocar um projeto em execução. Há mais de uma forma de executar esse back-end. Você verá tudo isso conosco a partir do próximo vídeo, porque eu já estou lá esperando por você.

Um forte abraço e nos vemos por aí.

Explorando o React Router - Uma rota pra cada página

Adicionando rotas restantes

Vamos continuar adicionando as demais rotas utilizando o componente Route, fornecido pelo React Router. Já temos duas configuradas: uma para quando acessamos a página inicial e outra para quando acessamos a rota de cadastro. No código do projeto, essa rota está como /cadastro. Ainda faltam algumas.

Vamos criar e declarar, de forma declarativa, uma rota para cada página que temos. Faremos isso de cima para baixo, com base nas páginas dentro da pasta "pages".

Criando rotas de perfil e edição

Vamos duplicar a linha de cadastro e criar o perfil. Temos o perfil e também o editar perfil. Pensando no fluxo de navegação, teremos uma página /perfil e uma /perfil/editar. Para editar o perfil, vamos chamar o componente EditProfile e realizar a importação no cabeçalho do arquivo. O VS Code já importou EditProfile para nós.

Veja como está, com a rota de edição de perfil já adicionada:

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import { BrowserRouter, Route, Routes } from 'react-router'
import Feed from './pages/Feed/index.tsx'
import Register from './pages/Register/index.tsx'
import EditProfile from './pages/EditProfile/index.tsx'

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Feed />} />
        <Route path="/cadastro" element={<Register />} />
        <Route path="/perfil/editar" element={<EditProfile />} />
      </Routes>
    </BrowserRouter>
  </StrictMode>,
)

Adicionando e organizando a rota de login

Em seguida, o feed (linha do tempo) já está configurado. Falta a rota de login (autenticação). Vamos alterar o path para /login e apontar para a nossa página de login; o nome do componente é Login, localizado em "pages". Vamos posicionar a rota /login próxima da rota de cadastro, para que fiquem visualmente lado a lado. Queremos organizar para manter rotas próximas ou parecidas juntas. Primeiro temos a página inicial (raiz /), depois /cadastro e /login, que são conceitualmente próximas entre si. Na prática, neste cenário, não faz diferença qual vem primeiro; queremos apenas deixá-las próximas para que, ao bater o olho, consigamos entender a organização.

Primeiro, adicionamos a rota de login (o VS Code realiza a importação do componente):

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import { BrowserRouter, Route, Routes } from 'react-router'
import Feed from './pages/Feed/index.tsx'
import Register from './pages/Register/index.tsx'
import EditProfile from './pages/EditProfile/index.tsx'
import Login from './pages/Login/index.tsx'

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Feed />} />
        <Route path="/cadastro" element={<Register />} />
        <Route path="/perfil/editar" element={<EditProfile />} />
        <Route path="/login" element={<Login />} />
      </Routes>
    </BrowserRouter>
  </StrictMode>,
)

Agora, apenas reorganizamos para manter /login próximo de /cadastro, deixando o arquivo mais legível:

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import { BrowserRouter, Route, Routes } from 'react-router'
import Feed from './pages/Feed/index.tsx'
import Register from './pages/Register/index.tsx'
import EditProfile from './pages/EditProfile/index.tsx'
import Login from './pages/Login/index.tsx'

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Feed />} />
        <Route path="/cadastro" element={<Register />} />
        <Route path="/login" element={<Login />} />
        <Route path="/perfil/editar" element={<EditProfile />} />
      </Routes>
    </BrowserRouter>
  </StrictMode>,
)

Definindo a rota de nova postagem

Agora temos um new post (nova publicação). Se estamos falando de publicação, vamos definir a rota /postagem, pois estamos usando rotas em português. Vamos utilizar o elemento NewPost e importar no topo do arquivo. O VS Code já realizou essa importação.

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import { BrowserRouter, Route, Routes } from 'react-router'
import Feed from './pages/Feed/index.tsx'
import Register from './pages/Register/index.tsx'
import EditProfile from './pages/EditProfile/index.tsx'
import Login from './pages/Login/index.tsx'
import NewPost from './pages/NewPost/index.tsx'

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Feed />} />
        <Route path="/cadastro" element={<Register />} />
        <Route path="/login" element={<Login />} />
        <Route path="/postagem" element={<NewPost />} />
        <Route path="/perfil/editar" element={<EditProfile />} />
      </Routes>
    </BrowserRouter>
  </StrictMode>,
)

Adicionando a rota de perfil

O que falta agora? O profile (perfil). Faremos o mesmo e vamos posicioná-lo próximo de /perfil/editar. Neste momento, adicionaremos apenas a rota /perfil. O nome do componente responsável pelo perfil é Profile, a página que representa o perfil. O VS Code realizou a importação. O Register (cadastro) nós já tínhamos.

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import { BrowserRouter, Route, Routes } from 'react-router'
import Feed from './pages/Feed/index.tsx'
import Register from './pages/Register/index.tsx'
import EditProfile from './pages/EditProfile/index.tsx'
import Login from './pages/Login/index.tsx'
import NewPost from './pages/NewPost/index.tsx'
import Profile from './pages/Profile/index.tsx'

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Feed />} />
        <Route path="/cadastro" element={<Register />} />
        <Route path="/login" element={<Login />} />
        <Route path="/postagem" element={<NewPost />} />
        <Route path="/perfil" element={<Profile />} />
        <Route path="/perfil/editar" element={<EditProfile />} />
      </Routes>
    </BrowserRouter>
  </StrictMode>,
)

Aprimorando a legibilidade do bloco de rotas

Vamos inserir um Enter no final e outro no início do bloco para organizar visualmente. Isso não altera o comportamento, apenas melhora a leitura:

import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import { BrowserRouter, Route, Routes } from 'react-router'
import Feed from './pages/Feed/index.tsx'
import Register from './pages/Register/index.tsx'
import EditProfile from './pages/EditProfile/index.tsx'
import Login from './pages/Login/index.tsx'
import NewPost from './pages/NewPost/index.tsx'
import Profile from './pages/Profile/index.tsx'

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <BrowserRouter>
      <Routes>
        
        <Route path="/" element={<Feed />} />
        <Route path="/cadastro" element={<Register />} />
        <Route path="/login" element={<Login />} />
        <Route path="/postagem" element={<NewPost />} />
        <Route path="/perfil" element={<Profile />} />
        <Route path="/perfil/editar" element={<EditProfile />} />
        
      </Routes>
    </BrowserRouter>
  </StrictMode>,
)

Resumindo as rotas e reforçando a passagem de elementos

Agora temos alguns blocos. Definimos uma rota para quando o path é /, isto é, a raiz, exibindo o componente Feed. Quando o caminho é /cadastro, usamos Register. Para /login, exibimos a página de login. Para publicação, usamos NewPost em /postagem. Para perfil, Profile em /perfil. E, para /perfil/editar, o elemento que queremos renderizar é EditProfile.

Precisamos ter um cuidado importante: queremos o JSX do componente. Não devemos passar o Feed dessa forma (por exemplo, como referência à função/componente sem JSX); precisamos passá-lo como componente, em sua forma JSX, usando a prop element={<Feed />} (o mesmo vale para Register, Login, NewPost, Profile e EditProfile), exatamente como fizemos nos trechos acima.

Testando as rotas e preparando a navegação

Com isso, declaramos todas as rotas da aplicação. Podemos ir ao navegador e testá-las. Vamos colocar lado a lado para testar uma por uma e reduzir o Chrome.

A página inicial renderiza Feed. Ao acessar /cadastro, a página de cadastro é exibida. Em /login, temos a página de login. Em /postagem, nova publicação, está funcionando. Em /perfil, a página de perfil também está funcionando. Por fim, em /perfil/editar, essa página também é renderizada corretamente.

Usando o modo declarativo do React Router, declaramos com componentes BrowserRouter, Routes e Route qual é o element. Essa estrutura segue exatamente o que a documentação orienta: para funcionar, precisa ser assim. O que mais utilizaremos é a rota do tipo Route, que possui um path e aponta para um element.

Neste momento, para navegar entre as páginas, precisamos alterar a URL manualmente. Isso não é confortável. Imagine as pessoas usuárias precisarem memorizar todos esses caminhos. Não. Agora precisamos pensar em uma forma de adicionar a navegação. Temos alguns links à disposição para que possamos realizar essa troca, e é isso que faremos a seguir.

Explorando o React Router - Explorando o código que recebemos

Contextualizando o projeto e objetivos

Como diria o ditado: bem começado é meio caminho andado. Antes de entrarmos no conteúdo novo, isto é, nas funcionalidades novas do React que vamos explorar neste curso, o primeiro passo é analisar o projeto base e entender por que desta vez não vamos começar do zero criando um projeto com Vite.

Já baixamos o projeto para nossa máquina. As instruções de como fazer isso estão em "Preparando o ambiente". Podemos clonar a partir do GitHub ou fazer o download do arquivo zip (arquivo compactado), abrir a pasta e seguir em frente. No nosso caso, o projeto já está em uma pasta no desktop chamada "Runner Circle", que é o nome do projeto. Vamos entrar nessa pasta e abrir o VS Code. Estamos realizando tudo pelo terminal, mas é possível fazer manualmente: ao abrir o VS Code, podemos acessar o menu File/Arquivo e escolher a opção Open Folder/Abrir pasta.

A base deste projeto é exatamente o que precisamos para detalhar e desenvolver as funcionalidades novas do React que vamos aprender. Seu core (núcleo) continua o mesmo: é um projeto Vite usando React e TypeScript.

Instalando dependências e executando a aplicação

Antes de olharmos o código, vamos vê-lo funcionando. No terminal, vamos executar npm i para instalar as dependências. O comando indicou, por acaso, que há três vulnerabilidades: uma moderada e uma alta. Para resolver, executamos npm audit fix. Essa é uma boa prática. Vamos ver se resolve. Perfeito, resolveu. Agora há zero vulnerabilidades. Isso é muito comum acontecer. Entre a publicação do projeto, a gravação do curso e o momento em que você executa, podem aparecer outras, e já sabemos como resolver. O npm audit fix identifica as vulnerabilidades conhecidas das versões em uso. No nosso caso, todas estavam em dependências de nossas dependências, bem no fundo da árvore, mas o processo conseguiu resolver e atualizar as versões necessárias. Note que o arquivo package-lock.json já foi modificado.

Com a base instalada, em vez de usar o terminal do VS Code, que fechamos e abrimos com frequência, vamos voltar ao terminal do sistema e executar npm run dev, que inicia a aplicação. Assim, ela fica disponível em localhost:5173.

Explorando as páginas e o layout inicial

Ao carregar, foi renderizada uma página de cadastro. O preenchimento exibido é o preenchimento automático do Chrome de dados já utilizados anteriormente. Ao realizar scroll (rolagem) para baixo, é exibida a página de login (entrada). Com mais um scroll (rolagem), aparece uma página de feed (linha do tempo), onde há publicações. Runner Circle é uma grande rede social para pessoas que apreciam correr. Já há um feed (linha do tempo) aqui; tudo está simulado e todos os cards são iguais, mas estão presentes. Também há uma página para criar uma nova publicação, ou seja, enviar e publicar uma corrida realizada. Há ainda a página de perfil, que mostra nossas publicações e nossos likes. Além disso, há a página de edição de perfil. E termina por aqui.

Todas as páginas estão empilhadas, uma em cima da outra. Isso ocorre porque vamos detalhar e adicionar funcionalidades. Neste momento, é apenas o layout.

Examinando a pasta components e seus elementos

Agora que vimos tudo funcionando, podemos olhar o código-fonte. Ao abrir a pasta "src", temos duas pastas separadas aqui dentro desta vez. A pasta "components" segue a mesma estrutura usada no curso anterior. Dentro de "components", há vários componentes pequenos: formulário, ações do formulário, campo do formulário, ícones, placeholder (marca de posição) de imagem e o ImageUploader, que é o componente exibido anteriormente. Na verdade, sabemos isso de memória.

É este componente aqui, onde está a opção de enviar imagens. Existem os seguintes componentes:

São todos componentes. Não vamos detalhá-los um a um. Vamos abrir um ao acaso: o textarea. Eles seguem a mesma estrutura que usamos no curso anterior. É um componente comum, com props devidamente tipadas.

Tipando componentes com ComponentProps e exemplificando o Textarea

Nesse cenário, usamos ComponentProps. Importamos ComponentProps de React e definimos que o textarea aceita qualquer propriedade que um elemento HTML textarea aceitaria. Em seguida, repassamos todas as propriedades recebidas para o elemento HTML. O TypeScript sabe o que o textarea aceita e o que não aceita.

Para ilustrar exatamente isso no código do projeto, o componente Textarea está implementado assim:

import type { ComponentProps } from 'react'
import styles from './Textarea.module.css'

type TextareaProps = ComponentProps<'textarea'>

function Textarea({ ...rest }: TextareaProps) {
    return <textarea className={styles.textarea} {...rest} />
}

export default Textarea

Esse componente tipa suas propriedades com ComponentProps<'textarea'>, permitindo passar qualquer prop válida de um <textarea> nativo, enquanto aplica um estilo próprio via CSS Modules.

Estilizando o Textarea com CSS Modules

Todo o projeto segue essa mesma estrutura. Quanto aos estilos, fazemos o mesmo que no curso anterior, utilizando CSS Modules. Portanto, no nível de componente, não há nada novo: é apenas layout, com TypeScript e props devidamente tipadas.

Para completar a visão, o arquivo de estilos CSS Module associado ao Textarea define a aparência do campo:

.textarea {
    width: 100%;
    min-height: 7.5rem;
    padding: 0.75rem 1rem;
    border: none;
    border-radius: 8px;
    background-color: var(--gray-input);
    font-size: 1rem;
    resize: none;
}

.textarea::placeholder {
    color: var(--text);
    opacity: 0.8;
}

.textarea:focus {
    outline: 2px solid var(--dark);
}

Detalhando as pages e planejando comportamentos

O que há de diferente? Esta parte que chamamos de "pages", que são as páginas:

A parte de layout está toda pronta. O que precisamos fazer é implementar comportamento. Se lembrarmos, no curso anterior começamos um projeto do zero, e uma das aulas foi dedicada apenas ao layout, ou seja, a codificar componentes. Trouxemos os componentes do nosso aplicativo Focus. Neste curso, desta vez, o projeto está começando do zero.

Você pode se aprofundar. Você pode usar um agente de IA e pedir que explique os componentes e todo o restante, se desejar. Fique à vontade. Por ora, isto é o que precisamos saber antes de começar.

Instalando o React DevTools e avançando para a navegação

Antes de começar, há uma última coisa que queremos mostrar. No navegador, vamos abrir o Developer Tools e a aba Console. Na Console, há uma mensagem dizendo: “Se quiser uma melhor experiência de desenvolvimento, experimente React DevTools”. Vamos clicar nesse link. Ele nos leva a uma página que explica o que o Developer Tools faz, como funciona, as diferentes extensões para os diversos navegadores e os recursos interessantes que oferece. Vamos abrir a página de instalação no Chrome e adicionar a extensão. Pronto. Ela já foi habilitada e aparece no canto superior direito.

Agora, no Runner Circle, vamos verificar se já aparece. Já está aqui. Como acabamos de instalá-la, vamos fechar o navegador, abri-lo novamente e acessar localhost:5173. Ao olhar as extensões, percebemos que antes a extensão do Developer Tools estava cinza; agora está vermelha. Portanto, foi identificada.

Onde ela aparece? No Developer Tools. Nas abas em que temos Elements, Console e assim por diante, podemos abri-la. Agora temos Components. Esse painel Components vai carregar e ler todos os componentes React. Tudo o que fizermos, tudo o que for acontecendo, aparecerá ali. Vale a pena deixar essa extensão ativa. Eventualmente, voltaremos a consultá-la.

Com tudo pronto e no lugar, vamos começar a desenvolver e decompor esta aplicação que tem todas essas páginas empilhadas. Precisamos começar a criar uma navegação entre elas. Esse tema é do próximo vídeo.

Sobre o curso React: construa uma aplicação front-end completa

O curso React: construa uma aplicação front-end completa possui 303 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