Skip to content

Commit 546f97c

Browse files
rvveberAntoLC
authored andcommitted
♻️(frontend) Refactor Auth component for improved redirection logic
Move redirects from render to a guarded useEffect to avoid triggering multiple redirects on every re-render.
1 parent af01c6e commit 546f97c

File tree

5 files changed

+91
-45
lines changed

5 files changed

+91
-45
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ and this project adheres to
1212

1313
### Changed
1414

15+
- ♻️(frontend) Refactor Auth component for improved redirection logic #1461
1516
- ♻️(frontend) replace Arial font-family with token font #1411
1617
- ♿(frontend) improve accessibility:
1718
- ♿(frontend) enable enter key to open documentss #1354

src/frontend/apps/impress/src/features/auth/components/Auth.tsx

Lines changed: 49 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import { Loader } from '@openfun/cunningham-react';
21
import { useRouter } from 'next/router';
3-
import { PropsWithChildren } from 'react';
2+
import { PropsWithChildren, useEffect, useState } from 'react';
43

5-
import { Box } from '@/components';
4+
import { Loading } from '@/components';
65
import { useConfig } from '@/core';
76

87
import { HOME_URL } from '../conf';
@@ -14,57 +13,65 @@ export const Auth = ({ children }: PropsWithChildren) => {
1413
useAuth();
1514
const { replace, pathname } = useRouter();
1615
const { data: config } = useConfig();
17-
18-
if (isLoading && !isFetchedAfterMount) {
19-
return (
20-
<Box $height="100vh" $width="100vw" $align="center" $justify="center">
21-
<Loader />
22-
</Box>
23-
);
24-
}
16+
const [isRedirecting, setIsRedirecting] = useState(false);
2517

2618
/**
27-
* If the user is authenticated and wanted initially to access a document,
28-
* we redirect to the document page.
19+
* If the user is authenticated and initially wanted to access a specific page, redirect him to that page now.
2920
*/
30-
if (authenticated) {
21+
useEffect(() => {
22+
if (!authenticated || isRedirecting) {
23+
return;
24+
}
25+
3126
const authUrl = getAuthUrl();
3227
if (authUrl) {
33-
void replace(authUrl);
34-
return (
35-
<Box $height="100vh" $width="100vw" $align="center" $justify="center">
36-
<Loader />
37-
</Box>
38-
);
28+
setIsRedirecting(true);
29+
void replace(authUrl).then(() => setIsRedirecting(false));
3930
}
40-
}
31+
}, [authenticated, isRedirecting, pathname, replace]);
4132

4233
/**
43-
* If the user is not authenticated and the path is not allowed, we redirect to the login page.
34+
* If the user is not authenticated and not on a allowed pages
4435
*/
45-
if (!authenticated && !pathAllowed) {
36+
useEffect(() => {
37+
if (isLoading || authenticated || pathAllowed || isRedirecting) {
38+
return;
39+
}
40+
41+
/**
42+
* The homepage feature is enabled, redirect them to the homepage
43+
*/
4644
if (config?.FRONTEND_HOMEPAGE_FEATURE_ENABLED) {
47-
void replace(HOME_URL);
48-
} else {
49-
gotoLogin();
45+
if (pathname !== HOME_URL) {
46+
setIsRedirecting(true);
47+
void replace(HOME_URL).then(() => setIsRedirecting(false));
48+
}
49+
50+
return;
5051
}
51-
return (
52-
<Box $height="100vh" $width="100vw" $align="center" $justify="center">
53-
<Loader />
54-
</Box>
55-
);
56-
}
5752

58-
/**
59-
* If the user is authenticated and the path is the home page, we redirect to the index.
60-
*/
61-
if (pathname === HOME_URL && authenticated) {
62-
void replace('/');
63-
return (
64-
<Box $height="100vh" $width="100vw" $align="center" $justify="center">
65-
<Loader />
66-
</Box>
67-
);
53+
/**
54+
* Redirect them to login page
55+
*/
56+
setIsRedirecting(true);
57+
gotoLogin();
58+
}, [
59+
authenticated,
60+
pathAllowed,
61+
config?.FRONTEND_HOMEPAGE_FEATURE_ENABLED,
62+
replace,
63+
isLoading,
64+
isRedirecting,
65+
pathname,
66+
]);
67+
68+
const shouldShowLoader =
69+
(isLoading && !isFetchedAfterMount) ||
70+
isRedirecting ||
71+
(!authenticated && !pathAllowed);
72+
73+
if (shouldShowLoader) {
74+
return <Loading $height="100vh" $width="100vw" />;
6875
}
6976

7077
return children;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { baseApiUrl } from '@/api';
22

3-
export const HOME_URL = '/home';
3+
export const HOME_URL: string = '/home';
44
export const LOGIN_URL = `${baseApiUrl()}authenticate/`;
55
export const LOGOUT_URL = `${baseApiUrl()}logout/`;
66
export const PATH_AUTH_LOCAL_STORAGE = 'docs-path-auth';

src/frontend/apps/impress/src/features/auth/utils.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
import { terminateCrispSession } from '@/services/Crisp';
22

3-
import { LOGIN_URL, LOGOUT_URL, PATH_AUTH_LOCAL_STORAGE } from './conf';
3+
import {
4+
HOME_URL,
5+
LOGIN_URL,
6+
LOGOUT_URL,
7+
PATH_AUTH_LOCAL_STORAGE,
8+
} from './conf';
49

10+
/**
11+
* Get the stored auth URL from local storage
12+
*/
513
export const getAuthUrl = () => {
614
const path_auth = localStorage.getItem(PATH_AUTH_LOCAL_STORAGE);
715
if (path_auth) {
@@ -10,8 +18,15 @@ export const getAuthUrl = () => {
1018
}
1119
};
1220

21+
/**
22+
* Store the current path in local storage if it's not the homepage or root
23+
* so we can redirect the user to this path after login
24+
*/
1325
export const setAuthUrl = () => {
14-
if (window.location.pathname !== '/') {
26+
if (
27+
window.location.pathname !== '/' &&
28+
window.location.pathname !== `${HOME_URL}/`
29+
) {
1530
localStorage.setItem(PATH_AUTH_LOCAL_STORAGE, window.location.pathname);
1631
}
1732
};

src/frontend/apps/impress/src/pages/home/index.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,30 @@
1+
import { useRouter } from 'next/router';
2+
import { useEffect } from 'react';
3+
4+
import { Loading } from '@/components';
5+
import { useAuth } from '@/features/auth';
16
import { HomeContent } from '@/features/home';
27
import { NextPageWithLayout } from '@/types/next';
38

49
const Page: NextPageWithLayout = () => {
10+
const { authenticated } = useAuth();
11+
const { replace } = useRouter();
12+
13+
/**
14+
* If the user is authenticated we redirect him to the index page (grid).
15+
*/
16+
useEffect(() => {
17+
if (!authenticated) {
18+
return;
19+
}
20+
21+
void replace('/');
22+
}, [authenticated, replace]);
23+
24+
if (authenticated) {
25+
return <Loading $height="100vh" $width="100vw" />;
26+
}
27+
528
return <HomeContent />;
629
};
730

0 commit comments

Comments
 (0)