Aula 23 – Golang – Fiber – React – Login e Redirect

Aula 23 – Golang – Fiber – React – Login e Redirect

Voltar para página principal do site

Todas as aulas desse curso

Aula 22                          Aula 24

Fiber

Fiber

Pacote Programador Fullstack

Pacote Programador Fullstack

Redes Sociais:

facebook        

Link para a Digital Innovation

Quer aprender python3 de graça e com certificado? Acesse então:

workover

Meus link de afiliados:

Hostinger

Digital Ocean

One.com

Código da aula: Github

Melhore seu NETWORKING

Participe de comunidades de desenvolvedores:

Fiquem a vontade para me adicionar ao linkedin.

E também para me seguir no GITHUB.

Canais do Youtube

Toti

Lofi Music Zone Beats

Backing Track / Play-Along

Código Fluente

Putz!

Vocal Techniques and Exercises

PIX para doações

PIX Nubank

PIX Nubank


Aula 23 – Golang – Fiber – React – Login e Redirect

Agora vamos completar o formulário de login.

Vamos criar algumas variáveis para gerenciar os estados dos inputs do formulário.


const [email, setEmail] = useState(''); 
const [password, setPassword] = useState(''); 
const [redirect, setRedirect] = useState(false);

Temos a função submit que está sendo usada para lidar com o evento de submissão de um formulário.


const submit = async (e: SyntheticEvent) => {
    e.preventDefault();
    // Os dados são passados como um objeto no segundo argumento da função post
    await axios.post("http://localhost:3000/api/login", {
      email: email,
      password: password,
    });
    setRedirect(true);
  };

const submit: Declaração da constante submit que contém a função.

async (e: SyntheticEvent): async indica que a função é assíncrona, permitindo o uso do await dentro dela. O e é o objeto do evento, e SyntheticEvent é um tipo do TypeScript que representa um evento sintético em React, ou seja, uma abstração dos eventos do DOM.

e.preventDefault(): Evita o comportamento padrão do evento, que seria submeter o formulário e recarregar a página.

axios.post: Utiliza o axios, uma biblioteca para fazer requisições HTTP, para enviar uma requisição POST ao endpoint especificado (‘http://localhost:3000/api/login‘). Isso é feito de maneira assíncrona, esperando a promessa ser resolvida ou rejeitada.

email: email,: Envia o estado email como parte do corpo da requisição POST.
password: password,: Envia o estado password como parte do corpo da requisição POST.

setRedirect(true);: Altera o estado redirect para true, o que provavelmente dispara uma navegação/redirecionamento no componente quando a resposta é recebida com sucesso.

A propriedade onChange em um elemento de entrada de formulário (input) no React é um manipulador de eventos que é acionado sempre que o valor do campo de entrada é alterado pelo usuário.

Aqui está o que acontece em cada um dos onChange:

onChange={e => setEmail(e.target.value)}: Quando o valor do campo de entrada do email é alterado, essa função anônima é chamada. Ela captura o evento, e então chama a função setEmail passando o valor atual do campo de entrada, que é acessado por e.target.value. Isso atualiza o estado email com o novo valor que o usuário digitou.

onChange={e => setPassword(e.target.value)}: Funciona da mesma forma que o manipulador onChange do campo de e-mail, mas em vez disso, atualiza o estado password.

Essas funções setEmail e setPassword são funções que são usadas para atualizar o estado de email e password, respectivamente, no componente.

Quando esses estados são atualizados, o componente é re-renderizado com os novos valores.

Isso é parte do que torna os formulários em React controlados, onde o estado do componente está em sincronia com os campos de entrada do formulário.

Veja as modificações em azul no código abaixo.

react-auth/src/pages/Login.tsx 


import React, { useState, SyntheticEvent } from 'react';
import axios from 'axios';
import { Navigate } from 'react-router-dom';

const Login: React.FC = () => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [redirect, setRedirect] = useState(false);
  const submit = async (e: SyntheticEvent) => {
    e.preventDefault();
    // Os dados são passados como um objeto no segundo argumento da função post
    await axios.post("http://localhost:3000/api/login", {
      email: email,
      password: password,
    });
    setRedirect(true);
  };

  if(redirect){
    return <Navigate to="/"/>;
  }
  return (
    <form className='form-floating' onSubmit={submit}>
      <h1 className="h3 mb-3 fw-normal">Please sign in</h1>
      <div className="form-signin">
        <input type="email" className="form-control" placeholder="name@example.com" required 
          onChange={e => setEmail(e.target.value)}
        />
      </div>
      <div className="form-signin">
        <input type="password" className="form-control" placeholder="Password" required 
          onChange={e => setPassword(e.target.value)}
        />
      </div>
      <button className="form-signin btn btn-primary w-100 py-2" type="submit">Sign in</button>
      <p className="mt-5 mb-3 text-body-secondary">&copy; 2017–2024</p>
    </form>
  );
}
export default Login;

Só fazer mais uma coisa antes de encerrar

Vamos refatorar a função submit().

Ao invés de usar URLs hardcoded, vamos criar os arquivos: .env.local para o ambiente de desenvolvimento local (este arquivo não deve ser commitado) e .env.production para produção.


react-auth/.env.local


# Configurações locais de desenvolvimento
REACT_APP_API_URL=http://localhost:3000
REACT_APP_FEATURE_FLAG_NEW_UI=true
REACT_APP_LOG_LEVEL=debug

react-auth/.env.production


# Configurações de produção
REACT_APP_API_URL=https://api.yourdomain.com
REACT_APP_FEATURE_FLAG_NEW_UI=false
REACT_APP_LOG_LEVEL=warning

E vamos também refatorar a função submit()

src/pages/Login.tsx 


import React, { useState, SyntheticEvent } from 'react';
import axios from 'axios';
import { Navigate } from 'react-router-dom';

const Login: React.FC = () => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [redirect, setRedirect] = useState(false);
  const submit = async (e: SyntheticEvent) => {
    e.preventDefault();

    // Usando variável de ambiente para a URL da API
    const apiURL = process.env.REACT_APP_API_URL || 'http://localhost:3000'; // Fallback para localhost se a variável de ambiente não estiver definida

    try {
        // Correção da chamada axios.post com a URL e os dados como argumentos separados
        const response = await axios.post(`${apiURL}/api/login`, {
          email, // Simplificação, já que o nome da propriedade e da variável são os mesmos
          password,
        });

        // Verifique a resposta aqui (exemplo: se o login foi bem-sucedido baseado no status da resposta)
        if (response.status === 200) {
          // Se a resposta for bem-sucedida, configure o estado para redirecionar
          setRedirect(true);
        } else {
          // Aqui, você pode tratar outros códigos de status ou definir um estado para exibir uma mensagem de erro
          console.error("Login falhou com status:", response.status);
          // Idealmente, definiria um estado de erro aqui para informar ao usuário que o login falhou
        }
      } catch (error) {
      console.error("Erro ao fazer login:", error);
      // Aqui, você também poderia definir um estado de erro para informar ao usuário sobre o problema
    }
  };

  if(redirect){
    return <Navigate to="/"/>;
  }
  return (
    <form className='form-floating' onSubmit={submit}>
      <h1 className="h3 mb-3 fw-normal">Please sign in</h1>
      <div className="form-signin">
        <input type="email" className="form-control" placeholder="name@example.com" required 
          onChange={e => setEmail(e.target.value)}
        />
      </div>
      <div className="form-signin">
        <input type="password" className="form-control" placeholder="Password" required 
          onChange={e => setPassword(e.target.value)}
        />
      </div>
      <button className="form-signin btn btn-primary w-100 py-2" type="submit">Sign in</button>
      <p className="mt-5 mb-3 text-body-secondary">&copy; 2017–2024</p>
    </form>
  );
}
export default Login;

A refatoração apresenta várias melhorias e práticas recomendadas sobre a implementação original.

Vamos detalhar as mudanças e o impacto de cada uma.

Uso de Variável de Ambiente para a URL da API

A refatoração introduz o uso de uma variável de ambiente (process.env.REACT_APP_API_URL) para definir a URL base da API.

Isso aumenta a flexibilidade e a segurança do código, permitindo que a URL base da API seja facilmente alterada sem a necessidade de modificar o código fonte, o que é particularmente útil para diferenciar ambientes de desenvolvimento, teste e produção.

Se a variável de ambiente não estiver definida, o código usa ‘http://localhost:3000‘ como fallback, garantindo que o sistema continue a funcionar mesmo sem configuração explícita.

Tratamento de Erros com Try/Catch

A inclusão de um bloco try/catch aprimora o manejo de erros ao realizar a requisição HTTP.

Isso significa que qualquer erro que ocorra durante a chamada à API (por exemplo, problemas de rede, erros de servidor, etc.) pode ser capturado e tratado de forma adequada, reduzindo a possibilidade de a aplicação falhar inesperadamente.

Verificação da Resposta da API

A refatoração inclui uma verificação explícita do status da resposta (response.status === 200).

Essa prática permite tratar diferentes cenários de resposta da API de maneira específica, como diferenciar entre um login bem-sucedido, credenciais inválidas, ou outros erros que a API possa retornar. Isso proporciona uma experiência de usuário mais rica e informativa.

Além disso, abre a possibilidade de implementar feedback específico para o usuário em caso de falha no login, melhorando a usabilidade da aplicação.

Simplificação da Passagem de Dados

O código refatorado utiliza uma forma simplificada para passar os dados para a função axios.post, aproveitando o recurso de propriedades de objeto de nomes iguais em ES6.

Se o nome da propriedade e o nome da variável são iguais, pode-se omitir o valor ({ email, password } em vez de { email: email, password: password }), tornando o código mais limpo e fácil de ler.

Feedback de Erro no Console

Enquanto a implementação original simplesmente redirecionava após a chamada de API sem verificar o resultado, a refatoração propõe registrar erros no console e sugere a possibilidade de definir estados de erro para informar ao usuário.

Embora mostrar erros diretamente no console seja mais uma ferramenta de desenvolvimento do que uma solução de UI para o usuário final, a menção de definir estados de erro é uma prática recomendada para fornecer feedback adequado ao usuário em caso de falhas.

react-auth/.env.local


# Configurações locais de desenvolvimento
REACT_APP_API_URL=http://localhost:3000
REACT_APP_FEATURE_FLAG_NEW_UI=true
REACT_APP_LOG_LEVEL=debug

react-auth/.env.production


# Configurações de produção
REACT_APP_API_URL=https://api.yourdomain.com
REACT_APP_FEATURE_FLAG_NEW_UI=false
REACT_APP_LOG_LEVEL=warning

E vamos também refatorar a função submit()

src/pages/Login.tsx 


import React, { useState, SyntheticEvent } from 'react';
import axios from 'axios';
import { Navigate } from 'react-router-dom';

const Login: React.FC = () => {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [redirect, setRedirect] = useState(false);
  const submit = async (e: SyntheticEvent) => {
    e.preventDefault();

    // Usando variável de ambiente para a URL da API
    const apiURL = process.env.REACT_APP_API_URL || 'http://localhost:3000'; // Fallback para localhost se a variável de ambiente não estiver definida

    try {
        // Correção da chamada axios.post com a URL e os dados como argumentos separados
        const response = await axios.post(`${apiURL}/api/login`, {
          email, // Simplificação, já que o nome da propriedade e da variável são os mesmos
          password,
        });

        // Verifique a resposta aqui (exemplo: se o login foi bem-sucedido baseado no status da resposta)
        if (response.status === 200) {
          // Se a resposta for bem-sucedida, configure o estado para redirecionar
          setRedirect(true);
        } else {
          // Aqui, você pode tratar outros códigos de status ou definir um estado para exibir uma mensagem de erro
          console.error("Login falhou com status:", response.status);
          // Idealmente, definiria um estado de erro aqui para informar ao usuário que o login falhou
        }
      } catch (error) {
      console.error("Erro ao fazer login:", error);
      // Aqui, você também poderia definir um estado de erro para informar ao usuário sobre o problema
    }
  };

  if(redirect){
    return <Navigate to="/"/>;
  }
  return (
    <form className='form-floating' onSubmit={submit}>
      <h1 className="h3 mb-3 fw-normal">Please sign in</h1>
      <div className="form-signin">
        <input type="email" className="form-control" placeholder="name@example.com" required 
          onChange={e => setEmail(e.target.value)}
        />
      </div>
      <div className="form-signin">
        <input type="password" className="form-control" placeholder="Password" required 
          onChange={e => setPassword(e.target.value)}
        />
      </div>
      <button className="form-signin btn btn-primary w-100 py-2" type="submit">Sign in</button>
      <p className="mt-5 mb-3 text-body-secondary">&copy; 2017–2024</p>
    </form>
  );
}
export default Login;

Com isso, encerramos essa aula.

Na próxima aula, seguimos na construção do frontend, e vamos fazer a parte de login e redirecting depois do login.

Código da aula: Github

Voltar para página principal do blog

Todas as aulas desse curso

Aula 22                          Aula 24

Redes Sociais:

facebook        

Novamente deixo meus link de afiliados:

Hostinger

Digital Ocean

One.com

É isso!

A gente se vê na próxima.

Até lá!

\o/

Bons estudos. 😉

About The Author
-

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>