I just want to send the non verified users to "/verify"
PrivateRoute
import React from 'react';
import { Navigate, Outlet } from 'react-router-dom';
import { useSelector } from 'react-redux';
const PrivateRoute = () => {
const isLoggedIn = useSelector((state: any) => state.auth.authentication);
const profile: any = isLoggedIn?.profile;
const isVerified: boolean = profile?.verified;
const hasSubscription: any = profile?.subscription;
console.log('verified: ', isVerified);
if (isLoggedIn) {
if (!isVerified) {
console.log('need to go to verify');
return <Navigate to='/verify' replace />;
} else {
return <Outlet />;
}
} else {
return <Navigate to='/login' />;
}
return <Navigate to='/login' />;
// return isLoggedIn ? <Outlet /> : <Navigate to='/login' />;
};
export default PrivateRoute;
app.tsx
<BrowserRouter>
<Routes>
<Route path='/login' element={<PublicRoute />}>
<Route path='/login' element={<Login />} />
</Route>
<Route path='/register' element={<PublicRoute />}>
<Route path='/register' element={<Register />} />
</Route>
<Route path='/reset-password' element={<PublicRoute />}>
<Route path='/reset-password' element={<ResetPassword />} />
</Route>
<Route path='/forgot-password' element={<PublicRoute />}>
<Route path='/forgot-password' element={<ForgetPassword />} />
</Route>
{/* <Route path='/subscription' element={<PublicRoute />}>
<Route path='/subscription' element={<Subscription />} />
</Route> */}
<Route path='/' element={<PrivateRoute />}>
<Route path='/verify' element={<Verify />} />
<Route path='/' element={<Main />}>
<Route path='/profile' element={<Profile />} />
<Route path='/socialcalendar' element={<SocialCalendar />} />
<Route path='/subscription' element={<Subscription />} />
<Route index element={<Navigate to='/socialcalendar' />} />
{/* <Route path='/' element={<Daily />} /> */}
{/* <Route path='/dashboard' element={<Dashboard />} /> */}
</Route>
</Route>
<Route path='*' element={<Navigate to='/login' />} />
</Routes>
</BrowserRouter>
It's just that when the user is not verified it goes to "/verify"
as seen in the url, but it just renders a blank page and no code from the verify page is being run.
I just want to get the verify page when user is not verified.
EDIT:
const login = async (email: string, password: string) => {
try {
console.log('login requesrt sent from login');
setAuthLoading(true);
const response: any = await authLogin(email, password);
dispatch(setAuthentication(response as any));
toast.success('Login is succeeded!');
setAuthLoading(false);
console.log(response.profile.verified);
await new Promise((resolve) => setTimeout(resolve, 100));
// if (!response.profile.verified) {
// navigate('/verify');
// } else {
// navigate('/socialcalendar')
// // if (
// // !response.profile?.subscription ||
// // response.profile.subscription.status === 'paused' ||
// // (response.profile.subscription.status === 'future' &&
// // response.profile.subscription.deleted === true) ||
// // response.profile.subscription.status === 'cancelled'
// // )
// // navigate('/subscription');
// // else navigate('/socialcalendar');
// }
navigate('/socialcalendar');
} catch (error: any) {
setAuthLoading(false);
toast.error(error.message || 'Failed');
}
};
the above is the code i am using for login.
as you can see I have to use that setTimeout , or else it loads the "/socialcalendar" instead of "/verify" no matter the user is verified or not
Protected routes can't redirect to other protected routes under the same layout route. This is likely creating a render loop of sorts where a resolved route isn't reachable because the UI keeps redirecting.
Move the "/verify"
route out of the layout route that protects it.
I suggest refactoring and splitting the PrivateRoute
component into two separate components. One that only checks if a user is authenticated, and the other that requires them to also be verified. The routes that are nested inside both PrivateRoute
and VerifiedRoute
will need both, while routes nested only inside PrivateRoute
need authentication. If users are not authenticated they are redirected to the login page, if they are missing the verification where it's needed they are redirected to the verify page.
import React from 'react';
import { Navigate, Outlet } from 'react-router-dom';
import { useSelector } from 'react-redux';
const PrivateRoute = () => {
const isLoggedIn = useSelector((state: any) => state.auth.authentication);
return isLoggedIn
? <Outlet />
: <Navigate to="/login" replace />;
};
export default PrivateRoute;
import React from 'react';
import { Navigate, Outlet } from 'react-router-dom';
import { useSelector } from 'react-redux';
const VerifiedRoute = () => {
const isVerified = useSelector((state: any) => {
return !!state.auth.authentication?.profile?.verified;
});
return isVerified
? <Outlet />
: <Navigate to='/verify' replace />;
};
export default VerifiedRoute;
<BrowserRouter>
<Routes>
<Route element={<PublicRoute />}>
<Route path='/login' element={<Login />} />
<Route path='/register' element={<Register />} />
<Route path='/reset-password' element={<ResetPassword />} />
<Route path='/forgot-password' element={<ForgetPassword />} />
<Route path='/subscription' element={<Subscription />} />
</Route>
<Route element={<PrivateRoute />}>
<Route path='/verify' element={<Verify />} /> // <-- outside VerifiedRoute
<Route element={<VerifiedRoute />}>
<Route element={<Main />}>
<Route path='/profile' element={<Profile />} />
<Route path='/socialcalendar' element={<SocialCalendar />} />
<Route path='/subscription' element={<Subscription />} />
<Route index element={<Navigate to='/socialcalendar' />} />
{/* <Route path='/' element={<Daily />} /> */}
{/* <Route path='/dashboard' element={<Dashboard />} /> */}
</Route>
</Route>
</Route>
<Route path='*' element={<Navigate to='/login' />} />
</Routes>
</BrowserRouter>