How I can fix my router? I am using redux to handle logout but when logout, it will direct me to 404 page then to login page. I tried to put exact
to the routes and made the 404 route last in the list of the routes. My website has different user roles so I think the bug is related to that.
<Routes>
<Route path={ROUTES.Error} element={<NotFound />} />
<Route path={ROUTES.home} element={<Private />}>
{pages
.filter((page) =>
page.hasAccess.some((role) =>
_.isEqual(role, user?.info?.RoleCode),
),
)
.map(({ id, path, element: Element }) => (
<>
<Route
key={id}
path={ROUTES.home}
element={<Navigate replace to="dashboard" />}
/>,
<Route key={id} path={path} element={<Element />} />
</>
))}
</Route>
<Route
path=""
element={<Public />}
children={<Route path={ROUTES.login} element={<Login />} />}
/>
</Routes>
Under saga Logout
function* logout() {
yield put(userSlice.actions.logoutFulfilled(null));
socket.disconnect();
yield new Promise(() => {
notification.success({
message: 'Success',
description: 'Logout Success',
});
});
}
CodePudding user response:
It seems the issue here is that the code is conditionally rendering routes based on the current user
object's roles. The protected routes are unmounted prior to any user check happening, so the UI momentarily renders the "404" route then the auth check occurs and redirects user to log in.
You should generally unconditionally render the routes so that they are always mounted and matchable, and use layout routes to render route protectors.
It's unclear what the Private
route is doing specifically, so I'll answer by suggesting you create a RoleWrapper
component that inspects a route's access roles against the current user.info.RoleCode
property. If the current user has the appropriate roles then the children
prop is rendered, otherwise a redirect to a safe, non-protected route is rendered.
const RoleWrapper = ({ children, roles }) => {
const { user } = /* however the user object is accessed */
// Handles initial mount if user object is fetched
if (user === undefined) {
return null; // or loading indicator/spinner/etc
}
const canAccess = roles.some(
(role) => _.isEqual(role, user?.info?.RoleCode),
);
return canAccess
? children
: <Navigate to="/dashboard" replace />; // or any safe route
};
<Routes>
<Route path={ROUTES.Error} element={<NotFound />} />
<Route path={ROUTES.home} element={<Private />}>
{pages.map(({ element: Element, hasAccess, id, path }) => (
<Route
key={id}
path={path}
element={(
<RoleWrapper roles={hasAccess}>
<Element />
</RoleWrapper>
)}
/>
))}
</Route>
<Route element={<Public />}>
<Route path={ROUTES.login} element={<Login />} />
</Route>
</Routes>
CodePudding user response:
It is very simple, you just have to use.
<Routes>
<Route path="*" element={<NotFound />} />
</Routes>