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
Redes Sociais:
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
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">© 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">© 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">© 2017–2024</p>
</form>
);
}
export default Login;