store token in cookie and redirect if token exist

This commit is contained in:
Guillaume Dorce 2022-09-09 10:06:27 +02:00
parent 173854a896
commit c2d96e6159
6 changed files with 95 additions and 41 deletions

View File

@ -10,7 +10,9 @@
},
"dependencies": {
"@tanstack/react-query": "^4.2.3",
"ms": "^2.1.3",
"react": "^18.2.0",
"react-cookie": "^4.1.1",
"react-dom": "^18.2.0",
"react-router-dom": "^6.3.0"
},

View File

@ -6,8 +6,10 @@ specifiers:
'@types/react-dom': ^18.0.6
'@vitejs/plugin-react': ^2.0.1
autoprefixer: ^10.4.8
ms: ^2.1.3
postcss: ^8.4.16
react: ^18.2.0
react-cookie: ^4.1.1
react-dom: ^18.2.0
react-router-dom: ^6.3.0
sass: ^1.54.8
@ -17,7 +19,9 @@ specifiers:
dependencies:
'@tanstack/react-query': 4.2.3_biqbaboplfbrettd7655fr4n2y
ms: 2.1.3
react: 18.2.0
react-cookie: 4.1.1_react@18.2.0
react-dom: 18.2.0_react@18.2.0
react-router-dom: 6.3.0_biqbaboplfbrettd7655fr4n2y
@ -399,9 +403,19 @@ packages:
use-sync-external-store: 1.2.0_react@18.2.0
dev: false
/@types/cookie/0.3.3:
resolution: {integrity: sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==}
dev: false
/@types/hoist-non-react-statics/3.3.1:
resolution: {integrity: sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==}
dependencies:
'@types/react': 18.0.17
hoist-non-react-statics: 3.3.2
dev: false
/@types/prop-types/15.7.5:
resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==}
dev: true
/@types/react-dom/18.0.6:
resolution: {integrity: sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA==}
@ -415,11 +429,9 @@ packages:
'@types/prop-types': 15.7.5
'@types/scheduler': 0.16.2
csstype: 3.1.0
dev: true
/@types/scheduler/0.16.2:
resolution: {integrity: sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==}
dev: true
/@types/use-sync-external-store/0.0.3:
resolution: {integrity: sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==}
@ -573,6 +585,11 @@ packages:
safe-buffer: 5.1.2
dev: true
/cookie/0.4.2:
resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==}
engines: {node: '>= 0.6'}
dev: false
/cssesc/3.0.0:
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
engines: {node: '>=4'}
@ -581,7 +598,6 @@ packages:
/csstype/3.1.0:
resolution: {integrity: sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==}
dev: true
/debug/4.3.4:
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
@ -922,6 +938,12 @@ packages:
'@babel/runtime': 7.18.9
dev: false
/hoist-non-react-statics/3.3.2:
resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
dependencies:
react-is: 16.13.1
dev: false
/immutable/4.1.0:
resolution: {integrity: sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==}
dev: true
@ -1011,6 +1033,10 @@ packages:
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
dev: true
/ms/2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
dev: false
/nanoid/3.3.4:
resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
@ -1133,6 +1159,17 @@ packages:
engines: {node: '>=10'}
dev: true
/react-cookie/4.1.1_react@18.2.0:
resolution: {integrity: sha512-ffn7Y7G4bXiFbnE+dKhHhbP+b8I34mH9jqnm8Llhj89zF4nPxPutxHT1suUqMeCEhLDBI7InYwf1tpaSoK5w8A==}
peerDependencies:
react: '>= 16.3.0'
dependencies:
'@types/hoist-non-react-statics': 3.3.1
hoist-non-react-statics: 3.3.2
react: 18.2.0
universal-cookie: 4.0.4
dev: false
/react-dom/18.2.0_react@18.2.0:
resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
peerDependencies:
@ -1143,6 +1180,10 @@ packages:
scheduler: 0.23.0
dev: false
/react-is/16.13.1:
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
dev: false
/react-refresh/0.14.0:
resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==}
engines: {node: '>=0.10.0'}
@ -1316,6 +1357,13 @@ packages:
hasBin: true
dev: true
/universal-cookie/4.0.4:
resolution: {integrity: sha512-lbRVHoOMtItjWbM7TwDLdl8wug7izB0tq3/YVKhT/ahB4VDvWMyvnADfnJI8y6fSvsjh51Ix7lTGC6Tn4rMPhw==}
dependencies:
'@types/cookie': 0.3.3
cookie: 0.4.2
dev: false
/update-browserslist-db/1.0.5_browserslist@4.21.3:
resolution: {integrity: sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==}
hasBin: true

View File

@ -1,13 +1,21 @@
import { Outlet } from 'react-router-dom';
import { BrowserRouter, Navigate, Outlet, Route, Routes } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import Login from './routes/login';
import Home from './routes/home';
// Create a client
const queryClient = new QueryClient();
export default () => {
return (
<BrowserRouter>
<QueryClientProvider client={queryClient}>
<Routes>
<Route path="/login" element={<Login />} />
<Route path="/home" element={<Home />} />
</Routes>
<Outlet />
</QueryClientProvider>
</BrowserRouter>
);
};

View File

@ -1,17 +1,5 @@
import ReactDOM from 'react-dom/client';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import App from './App';
import './index.css';
import Login from './routes/login';
import Signup from './routes/signup';
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<BrowserRouter>
<Routes>
<Route path="/" element={<App />}>
<Route path="login" element={<Login />} />
<Route path="signup" element={<Signup />} />
</Route>
</Routes>
</BrowserRouter>
);
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(<App />);

View File

@ -0,0 +1,18 @@
import { useCookies } from "react-cookie";
import { Navigate } from "react-router-dom";
const Home = () => {
const [cookie, setCookie] = useCookies(["token"]);
if (!cookie.token) {
return <Navigate to="/login" />;
}
return (
<div>
<h1>Home</h1>
</div>
);
}
export default Home;

View File

@ -1,11 +1,14 @@
import { Link } from 'react-router-dom';
import { Link, Navigate } from 'react-router-dom';
import logo from '@assets/images/logo.svg';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useState } from 'react';
import { useCookies } from 'react-cookie';
import ms from 'ms';
export default () => {
const Login = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [cookie, setCookie] = useCookies(['token']);
const queryClient = useQueryClient();
@ -24,10 +27,10 @@ export default () => {
},
{
onSuccess: (data) => {
console.log(data);
setCookie('token', data.token, { path: '/', expires: new Date(Date.now() + ms('1d')) });
},
onError: (error) => {
console.log(error);
console.error(error);
},
enabled: false,
refetchOnWindowFocus: false,
@ -37,30 +40,15 @@ export default () => {
const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
await refetch();
}
type Token = {
token: string;
userId: string;
expiresAt: string;
};
const useLogin = () => {
const token: Token | undefined = queryClient.getQueryData(['login'], { exact: true });
if (!token) {
alert('You are not logged in');
return;
}
alert(token.token);
}
return (
<>
{cookie.token ? <Navigate to="/home" /> : null}
<div className="flex flex-col min-h-full items-center justify-center py-12 px-4 bg-grey-dark sm:px-6 lg:px-8">
<div>
<img className="mx-auto h-20 pb-2 w-auto" src={logo} alt="Groupomania" />
</div>
<button className='rounded-lg bg-red text-white' onClick={() => useLogin()}>Test</button>
<div className="w-full max-w-md bg-grey rounded-lg p-5">
<form className="m-6 mb-3" action="#" method="POST" onSubmit={(e) => onSubmit(e)}>
<div className="-space-y-px rounded-md shadow-sm">
@ -116,3 +104,5 @@ export default () => {
</>
);
};
export default Login;