Skip to content

Commit

Permalink
feat: add no auth redirections
Browse files Browse the repository at this point in the history
  • Loading branch information
TomatoVan committed Dec 19, 2023
1 parent 2ba70dc commit f9b1a58
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 34 deletions.
11 changes: 7 additions & 4 deletions src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,26 @@ import { classNames } from 'shared/lib/classNames/classNames';
import { AppRouter } from 'app/providers/router';
import { Navbar } from 'widgets/Navbar';
import { Sidebar } from 'widgets/Sidebar';
import { useDispatch } from 'react-redux';
import { userActions } from 'entities/User';
import { useDispatch, useSelector } from 'react-redux';
import { getUserInited, userActions } from 'entities/User';
import { useTheme } from 'app/providers/ThemeProvider';

function App() {
const { theme } = useTheme();
const dispatch = useDispatch();
const inited = useSelector(getUserInited);

useEffect(() => {
dispatch(userActions.initAuthData());
}, [dispatch]);

return (
<div className={classNames('app', {}, [])}>
<div className={classNames('app', {}, [theme])}>
<Suspense fallback="">
<Navbar />
<div className="content-page">
<Sidebar />
<AppRouter />
{inited && <AppRouter />}
</div>
</Suspense>
</div>
Expand Down
44 changes: 15 additions & 29 deletions src/app/providers/router/ui/AppRouter.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,24 @@
import React, { memo, Suspense, useMemo } from 'react';
import React, { memo, Suspense, useCallback } from 'react';
import { Route, Routes } from 'react-router-dom';
import { routeConfig } from 'shared/config/routeConfig/routeConfig';
import {
AppRoutesProps,
routeConfig,
} from 'shared/config/routeConfig/routeConfig';
import { PageLoader } from 'shared/ui/PageLoader/PageLoader';
import { useSelector } from 'react-redux';
import { getUserAuthData } from 'entities/User';
import { RequireAuth } from 'app/providers/router/ui/RequireAuth';

const AppRouter = () => {
const isAuth = useSelector(getUserAuthData);
const renderWithWrapper = useCallback((route: AppRoutesProps) => {
const element = (
<Suspense fallback={<PageLoader />}>
<div className="page-wrapper">{route.element}</div>
</Suspense>
);

const routes = useMemo(() => Object.values(routeConfig).filter((route) => {
if (route.authOnly && !isAuth) {
return false;
}
return <Route key={route.path} path={route.path} element={route.authOnly ? <RequireAuth>{element}</RequireAuth> : element} />;
}, []);

return true;
}), [isAuth]);

return (
<Routes>
{routes.map(({ element, path }) => (
<Route
key={path}
path={path}
element={(
<Suspense fallback={<PageLoader />}>
<div className="page-wrapper">
{element}
</div>
</Suspense>
)}
/>
))}
</Routes>
);
return <Routes>{Object.values(routeConfig).map(renderWithWrapper)}</Routes>;
};

export default memo(AppRouter);
15 changes: 15 additions & 0 deletions src/app/providers/router/ui/RequireAuth.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { useSelector } from 'react-redux';
import { getUserAuthData } from 'entities/User';
import { Navigate, useLocation } from 'react-router-dom';
import { RoutePath } from 'shared/config/routeConfig/routeConfig';

export function RequireAuth({ children }: { children: JSX.Element }) {
const auth = useSelector(getUserAuthData);
const location = useLocation();

if (!auth) {
return <Navigate to={RoutePath.main} state={{ from: location }} replace />;
}

return children;
}
1 change: 1 addition & 0 deletions src/entities/User/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export { userReducer, userActions } from './model/slice/userSlice';
export { UserSchema, User } from './model/types/user';

export { getUserAuthData } from './model/selectors/getUserAuthData/getUserAuthData';
export { getUserInited } from './model/selectors/getUserInited/getUserInited';
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { StateSchema } from 'app/providers/StoreProvider';

export const getUserInited = (state: StateSchema) => state?.user._inited;
2 changes: 2 additions & 0 deletions src/entities/User/model/slice/userSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { USER_LOCALSTORAGE_KEY } from 'shared/const/localstorage';
import { User, UserSchema } from '../types/user';

const initialState: UserSchema = {
_inited: false,
};

export const userSlice = createSlice({
Expand All @@ -17,6 +18,7 @@ export const userSlice = createSlice({
if (user) {
state.authData = JSON.parse(user);
}
state._inited = true;
},
logout: (state) => {
state.authData = undefined;
Expand Down
1 change: 1 addition & 0 deletions src/entities/User/model/types/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ export interface User {

export interface UserSchema {
authData?: User;
_inited: boolean;
}
2 changes: 1 addition & 1 deletion src/shared/config/routeConfig/routeConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { AboutPage } from 'pages/AboutPage';
import { NotFoundPage } from 'pages/NotFoundPage';
import { ProfilePage } from 'pages/ProfilePage';

type AppRoutesProps = RouteProps & {
export type AppRoutesProps = RouteProps & {
authOnly?: boolean;
}

Expand Down

0 comments on commit f9b1a58

Please sign in to comment.