react-router optimizations

This commit is contained in:
proddy
2026-06-20 10:26:00 +02:00
parent 92d63d6f5d
commit 39b02591d9
12 changed files with 217 additions and 262 deletions

View File

@@ -1,17 +1,14 @@
import { memo, useContext } from 'react';
import type { FC } from 'react';
import { Navigate } from 'react-router';
import { Navigate, Outlet } from 'react-router';
import { AuthenticatedContext } from 'contexts/authentication';
import type { RequiredChildrenProps } from 'utils';
const RequireAdmin: FC<RequiredChildrenProps> = ({ children }) => {
const authenticatedContext = useContext(AuthenticatedContext);
return authenticatedContext.me.admin ? (
<>{children}</>
) : (
<Navigate replace to="/" />
);
// Layout-route guard: renders nested admin routes only for admins, otherwise
// redirects home. Must be used inside the authenticated route subtree so that
// AuthenticatedContext (and `me`) is available.
const RequireAdmin = () => {
const { me } = useContext(AuthenticatedContext);
return me.admin ? <Outlet /> : <Navigate replace to="/" />;
};
export default memo(RequireAdmin);

View File

@@ -0,0 +1,35 @@
import { memo, useContext, useEffect, useRef } from 'react';
import { Navigate } from 'react-router';
import { toast } from 'components/toast';
import { AuthenticationContext } from 'contexts/authentication';
import { useI18nContext } from 'i18n/i18n-react';
type RootRedirectKind = 'unauthorized' | 'fileUpdated';
// Shows a one-shot toast and bounces back to "/". Used by the /unauthorized and
// /fileUpdated routes. Resolves its own i18n message so it can be used directly
// as a static route element.
const RootRedirect = ({ kind }: { kind: RootRedirectKind }) => {
const { LL } = useI18nContext();
const { signOut } = useContext(AuthenticationContext);
const hasShownToast = useRef(false);
useEffect(() => {
// Guard against StrictMode double-invoke / re-renders.
if (hasShownToast.current) return;
hasShownToast.current = true;
if (kind === 'unauthorized') {
signOut(false);
toast.success(LL.PLEASE_SIGNIN());
} else {
toast.success(LL.UPLOAD_SUCCESSFUL());
}
// Run once on mount.
}, []);
return <Navigate to="/" replace />;
};
export default memo(RootRedirect);

View File

@@ -2,3 +2,4 @@ export { default as RouterTabs } from './RouterTabs';
export { default as RequireAdmin } from './RequireAdmin';
export { default as RequireAuthenticated } from './RequireAuthenticated';
export { default as RequireUnauthenticated } from './RequireUnauthenticated';
export { default as RootRedirect } from './RootRedirect';