♻️(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.
This commit is contained in:
@@ -12,6 +12,7 @@ and this project adheres to
|
||||
|
||||
### Changed
|
||||
|
||||
- ♻️(frontend) Refactor Auth component for improved redirection logic #1461
|
||||
- ♻️(frontend) replace Arial font-family with token font #1411
|
||||
- ♿(frontend) improve accessibility:
|
||||
- ♿(frontend) enable enter key to open documentss #1354
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { Loader } from '@openfun/cunningham-react';
|
||||
import { useRouter } from 'next/router';
|
||||
import { PropsWithChildren } from 'react';
|
||||
import { PropsWithChildren, useEffect, useState } from 'react';
|
||||
|
||||
import { Box } from '@/components';
|
||||
import { Loading } from '@/components';
|
||||
import { useConfig } from '@/core';
|
||||
|
||||
import { HOME_URL } from '../conf';
|
||||
@@ -14,57 +13,65 @@ export const Auth = ({ children }: PropsWithChildren) => {
|
||||
useAuth();
|
||||
const { replace, pathname } = useRouter();
|
||||
const { data: config } = useConfig();
|
||||
|
||||
if (isLoading && !isFetchedAfterMount) {
|
||||
return (
|
||||
<Box $height="100vh" $width="100vw" $align="center" $justify="center">
|
||||
<Loader />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
const [isRedirecting, setIsRedirecting] = useState(false);
|
||||
|
||||
/**
|
||||
* If the user is authenticated and wanted initially to access a document,
|
||||
* we redirect to the document page.
|
||||
* If the user is authenticated and initially wanted to access a specific page, redirect him to that page now.
|
||||
*/
|
||||
if (authenticated) {
|
||||
useEffect(() => {
|
||||
if (!authenticated || isRedirecting) {
|
||||
return;
|
||||
}
|
||||
|
||||
const authUrl = getAuthUrl();
|
||||
if (authUrl) {
|
||||
void replace(authUrl);
|
||||
return (
|
||||
<Box $height="100vh" $width="100vw" $align="center" $justify="center">
|
||||
<Loader />
|
||||
</Box>
|
||||
);
|
||||
setIsRedirecting(true);
|
||||
void replace(authUrl).then(() => setIsRedirecting(false));
|
||||
}
|
||||
}, [authenticated, isRedirecting, pathname, replace]);
|
||||
|
||||
/**
|
||||
* If the user is not authenticated and not on a allowed pages
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (isLoading || authenticated || pathAllowed || isRedirecting) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the user is not authenticated and the path is not allowed, we redirect to the login page.
|
||||
* The homepage feature is enabled, redirect them to the homepage
|
||||
*/
|
||||
if (!authenticated && !pathAllowed) {
|
||||
if (config?.FRONTEND_HOMEPAGE_FEATURE_ENABLED) {
|
||||
void replace(HOME_URL);
|
||||
} else {
|
||||
gotoLogin();
|
||||
if (pathname !== HOME_URL) {
|
||||
setIsRedirecting(true);
|
||||
void replace(HOME_URL).then(() => setIsRedirecting(false));
|
||||
}
|
||||
return (
|
||||
<Box $height="100vh" $width="100vw" $align="center" $justify="center">
|
||||
<Loader />
|
||||
</Box>
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the user is authenticated and the path is the home page, we redirect to the index.
|
||||
* Redirect them to login page
|
||||
*/
|
||||
if (pathname === HOME_URL && authenticated) {
|
||||
void replace('/');
|
||||
return (
|
||||
<Box $height="100vh" $width="100vw" $align="center" $justify="center">
|
||||
<Loader />
|
||||
</Box>
|
||||
);
|
||||
setIsRedirecting(true);
|
||||
gotoLogin();
|
||||
}, [
|
||||
authenticated,
|
||||
pathAllowed,
|
||||
config?.FRONTEND_HOMEPAGE_FEATURE_ENABLED,
|
||||
replace,
|
||||
isLoading,
|
||||
isRedirecting,
|
||||
pathname,
|
||||
]);
|
||||
|
||||
const shouldShowLoader =
|
||||
(isLoading && !isFetchedAfterMount) ||
|
||||
isRedirecting ||
|
||||
(!authenticated && !pathAllowed);
|
||||
|
||||
if (shouldShowLoader) {
|
||||
return <Loading $height="100vh" $width="100vw" />;
|
||||
}
|
||||
|
||||
return children;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { baseApiUrl } from '@/api';
|
||||
|
||||
export const HOME_URL = '/home';
|
||||
export const HOME_URL: string = '/home';
|
||||
export const LOGIN_URL = `${baseApiUrl()}authenticate/`;
|
||||
export const LOGOUT_URL = `${baseApiUrl()}logout/`;
|
||||
export const PATH_AUTH_LOCAL_STORAGE = 'docs-path-auth';
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
import { terminateCrispSession } from '@/services/Crisp';
|
||||
|
||||
import { LOGIN_URL, LOGOUT_URL, PATH_AUTH_LOCAL_STORAGE } from './conf';
|
||||
import {
|
||||
HOME_URL,
|
||||
LOGIN_URL,
|
||||
LOGOUT_URL,
|
||||
PATH_AUTH_LOCAL_STORAGE,
|
||||
} from './conf';
|
||||
|
||||
/**
|
||||
* Get the stored auth URL from local storage
|
||||
*/
|
||||
export const getAuthUrl = () => {
|
||||
const path_auth = localStorage.getItem(PATH_AUTH_LOCAL_STORAGE);
|
||||
if (path_auth) {
|
||||
@@ -10,8 +18,15 @@ export const getAuthUrl = () => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Store the current path in local storage if it's not the homepage or root
|
||||
* so we can redirect the user to this path after login
|
||||
*/
|
||||
export const setAuthUrl = () => {
|
||||
if (window.location.pathname !== '/') {
|
||||
if (
|
||||
window.location.pathname !== '/' &&
|
||||
window.location.pathname !== `${HOME_URL}/`
|
||||
) {
|
||||
localStorage.setItem(PATH_AUTH_LOCAL_STORAGE, window.location.pathname);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,7 +1,30 @@
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { Loading } from '@/components';
|
||||
import { useAuth } from '@/features/auth';
|
||||
import { HomeContent } from '@/features/home';
|
||||
import { NextPageWithLayout } from '@/types/next';
|
||||
|
||||
const Page: NextPageWithLayout = () => {
|
||||
const { authenticated } = useAuth();
|
||||
const { replace } = useRouter();
|
||||
|
||||
/**
|
||||
* If the user is authenticated we redirect him to the index page (grid).
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!authenticated) {
|
||||
return;
|
||||
}
|
||||
|
||||
void replace('/');
|
||||
}, [authenticated, replace]);
|
||||
|
||||
if (authenticated) {
|
||||
return <Loading $height="100vh" $width="100vw" />;
|
||||
}
|
||||
|
||||
return <HomeContent />;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user