Aula 25 – Golang – Fiber – React – Logout
Aula 25 – Golang – Fiber – React – Logout
Voltar para página principal do site
Todas as aulas desse curso
Aula 24 Aula 26
Redes Sociais do Código Fluente:
Scarlett Finch
Scarlett Finch é uma influenciadora virtual criada com IA.
Ela é 🎤 cantora e 🎶compositora pop britânica , 24 anos de idade, adora o Brasil e em especial o Rio de Janeiro.
Siga a Scarlett Finch no Instagram:
Conecte-se comigo!
LinkedIn: Fique à vontade para me adicionar no LinkedIn.
Ao conectar-se comigo, você terá acesso a atualizações regulares sobre desenvolvimento web, insights profissionais e oportunidades de networking no setor de tecnologia.
GitHub: Siga-me no GitHub para ficar por dentro dos meus projetos mais recentes, colaborar em código aberto ou simplesmente explorar os repositórios que eu contribuo, o que pode ajudar você a aprender mais sobre programação e desenvolvimento de software.
Recursos e Afiliados
Explorando os recursos abaixo, você ajuda a apoiar nosso site.
Somos parceiros afiliados das seguintes plataformas:
- https://heygen.com/ – Eleve a produção de seus vídeos com HeyGen! Com esta plataforma inovadora, você pode criar vídeos envolventes utilizando avatares personalizados, ideal para quem busca impactar e conectar com audiências em todo o mundo. HeyGen transforma a maneira como você cria conteúdo, oferecendo ferramentas fáceis de usar para produzir vídeos educativos, demonstrações de produtos e muito mais. Descubra o poder de comunicar através de avatares interativos e traga uma nova dimensão para seus projetos. Experimente HeyGen agora e revolucione sua forma de criar vídeos!
- letsrecast.ai – Redefina a maneira como você consome artigos com Recast. Esta plataforma transforma artigos longos em diálogos de áudio que são informativos, divertidos e fáceis de entender. Ideal para quem está sempre em movimento ou busca uma forma mais conveniente de se manter informado. Experimente Recast agora.
- dupdub.com – Explore o universo do marketing digital com DupDub. Esta plataforma oferece ferramentas inovadoras e soluções personalizadas para elevar a sua estratégia de marketing online. Ideal para empresas que buscam aumentar sua visibilidade e eficiência em campanhas digitais. Descubra mais sobre DupDub.
- DeepBrain AI Studios – Revolucione a criação de conteúdo com a tecnologia de inteligência artificial da DeepBrain AI Studios. Esta plataforma avançada permite que você crie vídeos interativos e apresentações utilizando avatares digitais gerados por IA, que podem simular conversas reais e interações humanas. Perfeito para educadores, criadores de conteúdo e empresas que querem inovar em suas comunicações digitais. Explore DeepBrain AI Studios.
- Audyo.ai – Transforme a maneira como você interage com conteúdo auditivo com Audyo.ai. Esta plataforma inovadora utiliza inteligência artificial para criar experiências de áudio personalizadas, melhorando a acessibilidade e a compreensão de informações através de podcasts, transcrições automáticas e síntese de voz avançada. Ideal para profissionais de mídia, educadores e qualquer pessoa que deseje acessar informações auditivas de maneira mais eficiente e envolvente. Descubra Audyo.ai e suas possibilidades.
- Acoust.io – Transforme sua produção de áudio com Acoust.io. Esta plataforma inovadora fornece uma suite completa de ferramentas para criação, edição e distribuição de áudio, ideal para artistas, produtores e empresas de mídia em busca de excelência e inovação sonora. Acoust.io simplifica o processo de levar suas ideias à realidade, oferecendo soluções de alta qualidade que elevam seus projetos de áudio. Experimente Acoust.io agora e descubra um novo patamar de possibilidades para seu conteúdo sonoro.
- Hostinger – Hospedagem web acessível e confiável. Ideal para quem busca soluções de hospedagem de sites com excelente custo-benefício e suporte ao cliente robusto. Saiba mais sobre a Hostinger.
- Digital Ocean – Infraestrutura de nuvem para desenvolvedores. Oferece uma plataforma de nuvem confiável e escalável projetada especificamente para desenvolvedores que precisam de servidores virtuais, armazenamento e networking. Explore a Digital Ocean.
- One.com – Soluções simples e poderosas para o seu site. Uma escolha ideal para quem busca registrar domínios, hospedar sites ou criar presença online com facilidade e eficiência. Visite One.com.
Educação e Networking
Amplie suas habilidades e sua rede participando de cursos gratuitos e comunidades de desenvolvedores:
- Digital Innovation One – Cursos gratuitos com certificado.
- Workover – Aprenda Python3 gratuitamente.
- Comunidades de desenvolvedores para networking:
Canais do Youtube
Explore nossos canais no YouTube para uma variedade de conteúdos educativos e de entretenimento, cada um com um foco único para enriquecer sua experiência de aprendizado e lazer.
Toti
Toti: Meu canal pessoal, onde posto clips artesanais de músicas que curto tocar, dicas de teoria musical, entre outras coisas.
Lofi Music Zone Beats
Lofi Music Zone Beats: O melhor da música Lofi para estudo, trabalho e relaxamento, criando o ambiente perfeito para sua concentração.
Backing Track / Play-Along
Backing Track / Play-Along: Acompanhe faixas instrumentais para prática musical, ideal para músicos que desejam aprimorar suas habilidades.
Código Fluente
Código Fluente: Aulas gratuitas de programação, devops, IA, entre outras coisas.
Putz!
Putz!: Canal da banda Putz!, uma banda virtual, criada durante a pandemia com mais 3 amigos, Fábio, Tatá e Lula.
Scarlett Finch
Scarlett Finch: Cantora e influenciadora criada com IA.
PIX para doações
Aula 25 – Golang – Fiber – React – Logout
Centralizando o Estado do Usuário no React para Melhoria da Gestão e Acessibilidade dos Dados
Para colocar o botão de logout no nav, precisamos do user no componente nav.
Como vamos fazer isso?
Em aplicações React, manter o estado relacionado ao usuário em um local centralizado é uma prática recomendada, especialmente em aplicações onde múltiplos componentes precisam acessar ou modificar esses dados.
No nosso caso, tanto o componente de navegação (Nav
) quanto a página inicial (Home
) necessitam acessar as informações do usuário.
Ao fazer a chamada do Axios para recuperar os dados do usuário no componente App
, que é o componente pai tanto de Nav
quanto de Home
, podemos facilmente passar esses dados como props para ambos os componentes.
Isso não só simplifica o fluxo de dados dentro da aplicação, como também facilita a manutenção, pois qualquer mudança relacionada à obtenção ou atualização dos dados do usuário pode ser gerenciada em um único local.
Além disso, isso nos permite implementar funcionalidades adicionais, como no caso desse projeto, um botão de logout no Nav
, de maneira mais eficiente.
O estado do usuário, estando disponível no App
, pode ser modificado diretamente de Nav
sem a necessidade de múltiplos handlers ou contextos complexos.
Isso garante que o estado do usuário seja consistentemente atualizado e refletido em toda a aplicação, melhorando a experiência do usuário e a confiabilidade da interface.
Essa abordagem de centralização do estado também prepara o terreno para uma eventual expansão do aplicativo, onde componentes adicionais poderão necessitar acessar ou modificar as informações do usuário sem necessitar de uma reestruturação significativa do gerenciamento de estado.
Portanto, ajustar nossa arquitetura para recuperar e gerenciar o estado do usuário no componente App
é uma decisão estratégica que melhora a eficiência do código e a escalabilidade da aplicação.
Vamos a prática!
Apague a parte em laranja do Home.tsx, porque estamos transferindo a chamada ao endpoint User, para o componente App.tsx, pai do Home.
src/pages/Home.tsx
import React, { useEffect } from 'react';
import axios from 'axios';
const Home: React.FC = () => {
const [message, setMessage] = useState('');
useEffect(() => {
(async () => {
try {
const response = await axios.get('user');
const user = response.data;
setMessage(`Hi ${user.first_name} ${user.last_name}`);
} catch (e) {
setMessage('You are not logged in!');
}
})();
}, []);
return (
<div className="container">
<h1>{message}</h1>
</div>
);
}
export default Home;
A parte laranja no código abaixo, ou seja, a parte das mensagens, pertencem ao Home, por isso, vamos voltar com elas para o Home e deixar só a parte em azul.
src/App.tsx
import React, { useState, useEffect } from "react";
import axios from "axios";
import "./App.css";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Login from "./pages/Login";
import Home from "./pages/Home";
import Register from "./pages/Register";
import Nav from "./components/Nav";
function App() {
useEffect(() => {
(async () => {
try {
const response = await axios.get('user');
const user = response.data;
setMessage(`Hi ${user.first_name} ${user.last_name}`);
} catch (e) {
setMessage('You are not logged in!');
}
})();
}, []);
return (
<div className="App">
<Router>
<Nav />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
</Routes>
</Router>
</div>
);
}
export default App;
Então o App.tsx agora tá assim:
src/App.tsx
import React, { useState, useEffect } from "react";
import axios from "axios";
import "./App.css";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Login from "./pages/Login";
import Home from "./pages/Home";
import Register from "./pages/Register";
import Nav from "./components/Nav";
function App() {
useEffect(() => {
(async () => {
try {
const response = await axios.get('user');
const user = response.data;
} catch (e) {
}
})();
}, []);
return (
<div className="App">
<Router>
<Nav />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
</Routes>
</Router>
</div>
);
}
export default App;
Além de trazer de volta as mensagens ao Home, vamos precisar pegar esse User que será enviado ao Home pelo App.tsx.
Para isso vamos receber no Home a propriedade do User e também definir suas propriedades, enviado pelo App.
Remova também os imports do axios
e o useEffect
, porque não vamos usar ele mais nesse arquivo.
src/pages/Home.tsx
import React, { useEffect } from 'react';
import axios from 'axios';
type UserProps = {
user: {
first_name: string;
last_name: string;
email?: string;
} | null; // Indicates that user can be an object with user data or null
};
const Home: React.FC<UserProps> = ({ user }) => {
let message;
if(user){
message = `Hi ${user.first_name} ${user.last_name}`;
} else{
message = 'You are not logged in!';
}
return (
<div className="container">
<h1>{message}</h1>
</div>
);
}
export default Home;
Com as modificações acima, o Home vai ficar assim:
src/pages/Home.tsx
import React from 'react';
type UserProps = {
user: {
first_name: string;
last_name: string;
email?: string;
} | null; // Indicates that user can be an object with user data or null
};
const Home: React.FC<UserProps> = ({ user }) => {
let message;
if(user){
message = `Hi ${user.first_name} ${user.last_name}`;
} else{
message = 'You are not logged in!';
}
return (
<div className="container">
<h1>{message}</h1>
</div>
);
}
export default Home
Já que a chamada ao endpoint User está sendo no App.tsx, precisamos passar ele como uma propriedade para o componente Home.
src/App.tsx
import React, { useState, useEffect } from "react";
import axios from "axios";
import "./App.css";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Login from "./pages/Login";
import Home from "./pages/Home";
import Register from "./pages/Register";
import Nav from "./components/Nav";
function App() {
const [user, setUser] = useState(null); // Adding state to store user data
useEffect(() => {
(async () => {
try {
const response = await axios.get('user');
const user = response.data;
setUser(user);
} catch (e) {
setUser(null);
}
})();
}, []);
return (
<div className="App">
<Router>
<Nav user={user}/>
<Routes>
<Route path="/"element={<Home user={user} />} /> // Passing the user to Home
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
</Routes>
</Router>
</div>
);
}
export default App;
E da mesma forma que fizemos para receber as propriedades do User enviado do App para o Home, faremos também do mesmo jeito, no Nav.
Vamos também transferir a parte em vermelho e trocar por {links}.
src/components/Nav.tsx
import React, { useState } from 'react';
import axios from "axios";
import { Link } from "react-router-dom";
const Nav = ({ user }: { user: any }) => {
const [isNavCollapsed, setIsNavCollapsed] = useState(true);
const handleNavCollapse = () => setIsNavCollapsed(!isNavCollapsed);
return (
<nav className="navbar navbar-expand-lg navbar-dark bg-dark">
<div className="container-fluid">
<Link className="navbar-brand" to="/">Home</Link>
<button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded={!isNavCollapsed} aria-label="Toggle navigation" onClick={handleNavCollapse}>
<span className="navbar-toggler-icon"></span>
</button>
<div className={`${isNavCollapsed ? 'collapse' : ''} navbar-collapse`} id="navbarNav">
<ul className="navbar-nav ms-auto">
<li className="nav-item">
<Link className="nav-link" to="/login">Login</Link>
</li>
<li className="nav-item">
<Link className="nav-link" to="/register">Register</Link>
</li>
</ul>
</div>
</div>
</nav>
);
};
export default Nav;
Vamos modificar o html do Nav e também verificar se o usuário está logado, se estiver, será mostrado no Nav o Logout, caso contrário, será mostrado Login e Register.
src/components/Nav.tsx
import React, { useState } from 'react';
import axios from "axios";
import { Link } from "react-router-dom";
const Nav = ({ user }: { user: any }) => {
const logout = async () => {
await axios.post('logout', {});
}
let links;
if(user){
links = (
<ul className="navbar-nav ms-auto">
<li className="nav-item">
<Link className="nav-link" to="/" onClick={logout}>Logout</Link>
</li>
</ul>
)
} else {
links = (
<ul className="navbar-nav ms-auto">
<li className="nav-item">
<Link className="nav-link" to="/login">Login</Link>
</li>
<li className="nav-item">
<Link className="nav-link" to="/register">Register</Link>
</li>
</ul>
)
}
const [isNavCollapsed, setIsNavCollapsed] = useState(true);
const handleNavCollapse = () => setIsNavCollapsed(!isNavCollapsed);
return (
<nav className="navbar navbar-expand-lg navbar-dark bg-dark">
<div className="container-fluid">
<Link className="navbar-brand" to="/">Home</Link>
<button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded={!isNavCollapsed} aria-label="Toggle navigation" onClick={handleNavCollapse}>
<span className="navbar-toggler-icon"></span>
</button>
<div className={`${isNavCollapsed ? 'collapse' : ''} navbar-collapse`} id="navbarNav">
<ul className="navbar-nav ms-auto">
{links}
</ul>
</div>
</div>
</nav>
);
};
export default Nav;
Testando
Veja que se você deslogar, ou logar caso esteja deslogado, a página não muda, a não ser que a gente recarregue a página dando um refresh.
Vamos mudar mais algumas coisas no App, Login e Nav para resolver isso.
src/App.tsx
import React, { useState, useEffect } from "react";
import axios from "axios";
import "./App.css";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import Login from "./pages/Login";
import Home from "./pages/Home";
import Register from "./pages/Register";
import Nav from "./components/Nav";
function App() {
const [user, setUser] = useState(null); // State to store user data
const [login, setLogin] = useState(false);
useEffect(() => {
(async () => {
try {
const response = await axios.get("user");
const user = response.data;
setUser(user);// Update the state with user data
} catch (e) {
console.error("Error loading user data", e);
setUser(null); // Sets the user to null in case of error
}
})();
}, [login]);
return (
<div className="App">
<Router>
<Nav user={user} setLogin={ () => setLogin(false) }/>
<Routes>
<Route path="/" element={<Home user={user} />} />
<Route path="/login" element={<Login setLogin={() => setLogin(true)} />} />
<Route path="/register" element={<Register />} />
</Routes>
</Router>
</div>
);
}
export default App;
Estado login
: A adição da variável login
permite rastrear quando um login ou logout ocorre.
Essa variável é usada como uma dependência no useEffect
, o que significa que cada vez que login
é atualizado (login bem-sucedido ou logout), o useEffect
é disparado novamente.
Objetivo: Recarregar as informações do usuário quando o status de login muda, sem precisar recarregar toda a página.
Isso melhora a experiência do usuário e torna a aplicação mais responsiva e eficiente.
A outra mudança foi do <Route path="/login" element={<Login />} />
para<Route path="/login" element={<Login setLogin={() => setLogin(true)} />} />
.
Essa mudança consiste em adicionar uma propriedade ao componente Login
.
Ao incluir setLogin={() => setLogin(true)}
, você está passando uma função que atualiza o estado de login na aplicação quando o usuário efetua login com sucesso.
Isso permite que o componente Login
interaja diretamente com o estado global de autenticação, atualizando-o conforme necessário sem precisar de recarregamento da página, facilitando o controle de acesso e a resposta imediata da interface ao estado de autenticação do usuário.
Agora no Login faça as mudanças indicada em azul no código abaixo.
src/pages/Login.tsx
import React, { useState, SyntheticEvent } from 'react';
import axios from 'axios';
import { Navigate } from 'react-router-dom';
const Login: React.FC<{ setLogin: (loggedIn: boolean) => void }> = ({ setLogin }) => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [redirect, setRedirect] = useState(false);
const submit = async (e: SyntheticEvent) => {
e.preventDefault();
// Using environment variable for API URL
const apiURL = process.env.REACT_APP_API_URL || 'http://localhost:3000'; // Fallback to localhost if environment variable is not set
try {
// Fix axios.post call with URL and data as separate arguments
const response = await axios.post(`${apiURL}/api/login`, {
email, // Simplification, since the name of the property and variable are the same
password,
});
// Check the response here (example: whether login was successful based on the response status)
if (response.status === 200) {
// If the response is successful, set the state to redirect
setLogin(true);
setRedirect(true);
} else {
// Here you can handle other status codes or set a state to display an error message
console.error("Login falhou com status:", response.status);
// Ideally I would set an error state here to inform the user that login failed
}
} catch (error) {
console.error("Erro ao fazer login:", error);
// Here you could also set an error state to inform the user about the problem
}
};
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;