Alura > Cursos de Front-end > Cursos de React > Conteúdos de React > Primeiras aulas do curso React: integração com Supabase e conceitos de arquitetura limpa na prática

React: integração com Supabase e conceitos de arquitetura limpa na prática

Criando usuários - Apresentação

Olá! Boas-vindas a mais este curso de React com o Vinicios Neves.

Audiodescrição: Vinicios é um homem de pele clara, careca e de barba escura que usa óculos de aro preto. Ele veste um moletom amarelo e tem, ao fundo, uma parede lisa iluminada pelas cores azul e rosa.

O que vamos aprender?

Vamos desenvolver uma aplicação React baseada nos conceitos de arquitetura limpa.

Nós vamos trabalhar em uma aplicação que já possui a camada visual pronta, portanto, não iremos modificar o CSS durante este curso. No entanto, desenvolveremos várias funcionalidades, como login, logout e integrações com o Supabase.

Atualmente, estamos com a aplicação em execução. Vamos realizar um logout para demonstrar seu funcionamento. Em seguida, faremos login com meu usuário, que já possui algumas transações cadastradas. A rotina de login está funcionando corretamente. Temos uma rota protegida, onde, se o usuário não estiver logado, ele não consegue acessar o dashboard. Tudo isso está conectado ao Supabase, ou seja, teremos um back-end como serviço.

Há muitas funcionalidades interessantes que podemos implementar, incluindo um desafio especial que preparamos para você no final.

Para quem é este curso?

Se você já está familiarizado com o funcionamento do React e com a criação de componentes e conceitos de API, este curso é ideal para você. Além disso, reforçaremos o conceito de arquitetura limpa, que está mais próximo do back-end.

Vamos desenvolver uma aplicação totalmente funcional que você poderá publicar e adicionar ao seu portfólio. Aguardamos você no próximo vídeo para começarmos a programar.

Criando usuários - Caso de uso : criando usuários

Vamos começar a evoluir o AnyBank? Vamos abrir o terminal. Já baixamos o projeto inicial. As instruções estão na atividade "Preparando o Ambiente", você pode baixá-lo também.

Já rodamos o npm install para instalar as dependências. Agora, vamos abrir o VSCode dentro do projeto e pedir para o npm executar o script de dev (npm run dev) para levantar a aplicação no localhost:5173. Podemos dar uma olhada nela para ver com o que vamos trabalhar.

Explorando o projeto

A página inicial já está carregada. O que queremos destacar neste primeiro momento é que a camada visual já está desenvolvida, mas não possui comportamento algum. O único comportamento existente é o de navegação. Podemos navegar para a página de cadastro clicando em "Abrir conta" e para a página de login clicando em "Login". Quando clicamos no logo do AnyBank, voltamos para a página inicial. Esse é o único comportamento desenvolvido até agora.

Se observarmos o projeto no VSCode, vamos abrir o arquivo que está em "src > router > index.tsx". Este é o nosso roteador, e estamos usando o react-router-dom neste projeto.

import { createBrowserRouter } from "react-router-dom";
import Home from "../Home";
import RootLayout from "../RootLayout";
import Login from "../Login";
import Register from "../Register";
import AuthLayout from "../AuthLayout";

export const router = createBrowserRouter([
  {
    path: "/",
    element: <RootLayout />,
    children: [
      {
        path: "",
        element: <Home />,
      },
      {
        path: "/auth",
        element: <AuthLayout />,
        children: [
          {
            path: "login",
            element: <Login />,
          },
          {
            path: "register",
            element: <Register />,
          },
        ]
      },
    ],
  },
]);

Vamos destacar alguns pontos de atenção. Primeiro, temos um RootLayout. Vamos fazer um Ctrl + Clique para entrar nele, que basicamente organiza o Header e renderiza o Outlet.

const RootLayout = () => {

    return (
        <>
            <Header />
            <Container>
                <Outlet />
            </Container>
        </>
    )
}

Além disso, temos o AuthLayout, que é um layout específico que renderiza tudo dentro de um card.

const AuthLayout = () => {

    return (
        <Card>
            <Outlet />
        </Card>
    )
}

Na tela, ao clicar em "Abrir conta" e "Login", esse card já está organizado no projeto.

Temos três rotas disponíveis: a página inicial, que é a rota /, um grupo de rotas que é /auth, e dentro desse grupo temos /auth/login e /auth/register. Com isso, temos a base necessária para começar.

Se você tiver dificuldade para ver como esses componentes foram desenvolvidos, vamos dar detalhes sobre um específico, e você pode explorar os outros.

Por exemplo, no componente "Button", no "index.tsx", estamos usando Styled Components. Há várias coisas já desenvolvidas focadas no CSS e no layout. Essa é a base do projeto. Toda a camada visual já está pronta.

Pensando os casos de uso

Agora que falamos sobre isso, por onde vamos começar? Vamos voltar ao navegador e focar na parte de login. Vamos começar a pensar nas interações com a aplicação como se fosse um caso de uso. Temos um cenário onde a pessoa usuária gostaria de executar o login ou, olhando para o cadastro, gostaria de se cadastrar na aplicação. Com esse pensamento, vamos organizar isso e pensar em um caso de uso para o nosso cadastro.

Vamos para o VSCode. Dentro de "src", vamos criar uma pasta chamada "domain". Vamos criar uma pasta chamada "domain" porque ela representa o domínio da nossa aplicação. Tudo que estiver mais próximo da regra de negócio e de como a aplicação deve se comportar, e menos da parte de implementação, como CSS, modules ou styled components, começamos a separar.

Dentro dessa pasta "domain", vamos criar três pastas. A primeira será "useCases". Já conversamos que vamos organizar nosso pensamento baseado em casos de uso, então serão "useCases".

O código está todo em inglês, então vamos manter esse padrão, mas traduziremos os termos conforme necessário.

Vamos criar também outra pasta dentro de "domain", chamada "Entities". Pensando em entidade, podemos começar pensando no fluxo da aplicação com o cadastro. Precisamos imaginar como será a interface da pessoa usuária.

Implementando a parte de cadastro

Vamos criar um novo arquivo no VSCode, chamá-lo de "IUser.ts", e criar uma interface e já exportá-la:

export interface IUser {
  id: string;
  name: string;
  email: string;
  password: string;
}

No projeto, optamos por indicar interfaces com o prefixo I, uma convenção que trazemos do C#. Isso ajuda a identificar interfaces rapidamente. Se preferir, você pode não usar esse prefixo, mas neste projeto, usaremos I para indicar interfaces.

Pensando no formato da pessoa usuária, temos id, name, email e password, todos como string. Esses campos vêm da nossa página de cadastro.

Dando sequência, vamos pensar no nosso caso de uso. Dentro de "useCases", vamos criar o nosso primeiro caso de uso, chamado "CreateUser.ts". Vamos exportar uma classe com o mesmo nome:

export class CreateUser {
  execute(user: IUser) {

  }
}

Queremos executar uma ação, então chamaremos um método execute, que receberá um usuário por parâmetro. Queremos cadastrar esse usuário em algum lugar, mas não queremos detalhes dessa implementação agora. Vamos criar um código que não compila, mas serve para começarmos a desenvolver. Vamos criar um construtor para essa classe:

export class CreateUser {
    constructor(private userRepository: IUserRepository) {}
    execute(user: IUser) {

  }
}

Queremos que o construtor receba um repositório de usuário, responsável por cadastrar o usuário. O tipo será IUserRepository, e ele será injetado. A classe IUserRepository ainda não existe, então vamos criá-la.

Dentro de "domain", vamos criar uma pasta chamada "repositories" e criar a interface IUserRepository.ts:

export interface IUserRepository {
  createUser(user: Omit<IUser, 'id'>): Promise<void>;
}

Essa interface terá um método createUser, que receberá um usuário sem o id, pois ele deve ser criado depois. O método será assíncrono, retornando uma Promise<void>.

No arquivo "CreateUser", vamos implementar o método execute. Porém, como o repositório não receberá o id logo de cara, isso também não acontece na execução. Em seguida, faremos um this. userRepository já injetado e chamar o createUser passando o usuário que acabamos de receber. Podemos dizer uqe o método é assíncrono acrescentando async na frente ou indicá-lo como uma Promise<void>.

export class CreateUser {
    constructor(private userRepository: IUserRepository) {}
    async execute(user: Omit<IUser, 'id'>) {
        this.userRepository.createUser(user);
    }
}

Agora temos o nosso caso de uso, o repositório e a interface, mas ainda está abstrato. Precisamos pensar na camada mais concreta: qual será o repositório que realmente cadastrará o usuário? Vamos fazer isso no próximo vídeo.

Criando usuários - Criando o projeto no Supabase

Nós terminamos nosso último encontro com a camada abstrata já implementada. Criamos as interfaces e nos perguntamos onde vamos cadastrar esses usuários. Neste curso, trabalharemos com o Supabase. Já criamos uma conta, que é gratuita, e o login já está feito. É um processo simples de criação de conta, e agora vamos criar um novo projeto.

Criando um novo projeto

Na página inicial, não temos nenhum projeto ainda porque criamos uma conta especificamente para este curso. Vamos clicar no botão "New Project" no centro da tela para solicitar um novo projeto. Na nova página que carregou, manteremos o campo "Organization" como está, pois é apenas para teste.

No campo "Project name", escreveremos "anybank" e clicaremos com o botão direito do mouse no campo "Database Password", selecionando "Suggest a strong password", para o Google Chrome sugerir uma senha, que podemos recuperar se necessário.

Selecionamos uma região próxima do Vinicios, optando por "West Europe (London)". Após isso, clicamos em "Create New Project" na parte inferior direita da página. Esses são os passos necessários para criar um novo projeto.

Atualizamos a senha e aguardamos alguns minutos até que o projeto esteja disponível. Ele gera alguns segredos, e agora podemos começar a trabalhar na aplicação. Dentro do projeto recém-criado, há um botão chamado "Client Docs", logo abaixo do título "Project API Keys" e do texto que o acompanha.

Ao clicarmos nesse botão, uma nova aba será aberta no navegador. Na nova página, selecionaremos "JavaScript", ao lado do menu "Client Libraries", que nos instrui a instalar o Supabase no projeto usando o comando:

npm install @supabase/supabase-js

Instalando e configurando o Supabase

Executamos o comando no terminal e deixamos o Supabase instalar. No final, é necessário importar o createClient do próprio Supabase. Vamos pensar na estrutura e onde podemos fazer isso. Fechamos o terminal e colapsamos as partes de componentes, domínio e router.

Queremos começar a pensar na camada de infraestrutura do projeto. Chamamos de infraestrutura a parte onde o Supabase será implementado. Amanhã ou depois, podemos trocar o Supabase pelo Firebase ou por um backend customizado. Essa é a parte de infraestrutura, que está mais próxima dos bytes e da forma como os dados são armazenados.

Criamos uma pasta dentro do "src" chamada "infra", abreviando "infraestrutura". Dentro dessa pasta, criamos outra chamada "supabase", pois podemos ter outras camadas e integrações relacionadas à infraestrutura. Dentro da pasta "supabase", criamos um arquivo chamado "config.ts", que será a configuração do nosso Supabase.

No arquivo "config.ts", fazemos um export const supabase, que será o resultado do método createClient(). O VS Code sugere a importação, e precisamos passar para o createClient() a supabaseUrl e a supabaseKey. Não queremos colocar isso diretamente no código, então utilizamos variáveis de ambiente.

Criamos uma constante chamada supabaseUrl, que será uma string, e pegamos isso de import.meta.env.VITE_SUPABASE_URL. Essa é a forma que o Vite entrega variáveis de ambiente. O prefixo VITE_SUPABASE_URL é necessário para que as variáveis fiquem disponíveis no lado do cliente.

Se colocássemos apenas supabaseUrl, o Vite não entregaria, e a variável ficaria indefinida.

Precisamos também da supabaseKey, então duplicamos a linha e trocamos Url por Key, e VITE_SUPABASE_URL por VITE_SUPABASE_KEY. Com isso, podemos passar esses valores para o createClient.

import { createClient } from "@supabase/supabase-js";

const supabaseUrl: string = import.meta.env.VITE_SUPABASE_URL
const supabaseKey: string = import.meta.env.VITE_SUPABASE_KEY

export const supabase = createClient(supabaseUrl, supabaseKey)

Na raiz do projeto, criamos um arquivo chamado ".env". Porém, não queremos que esse arquivo seja enviado para o Git, pois não queremos que as variáveis fiquem disponíveis no GitHub. Por isso, chamaremos ".env.local". O próprio .gitignore do Vite já ignora o .env.local.

Agora, precisamos trazer os valores das variáveis VITE_SUPABASE_URL e VITE_SUPABASE_KEY para o arquivo ".env.local".

VITE_SUPABASE_URL=""
VITE_SUPABASE_KEY=""

Com sorte, o Supabase já terminou de configurar o projeto. No Supabase, na nossa organização, verificamos que o projeto está configurado. Ele fornece o "Project URL" e a "API Key", que são seguros para uso no navegador, desde que tomemos cuidado com a criação das tabelas.

Copiamos o "Project URL" e colamos no ".env.local", assim como a "API Key". Esses são os passos para configurar o Supabase. Agora, precisamos começar a criar os repositórios usando o Supabase. Vamos fazer isso no próximo vídeo.

Sobre o curso React: integração com Supabase e conceitos de arquitetura limpa na prática

O curso React: integração com Supabase e conceitos de arquitetura limpa na prática possui 149 minutos de vídeos, em um total de 49 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