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