Приватные роуты в React
Такой вопрос, есть страницы доступные для всех пользователей, а есть страницы которые доступны только тем кто авторизован на сайте, в моем случае страничка профиля пользователя, пытаюсь отделить роуты на данные страницы, но не получается, при этом при авторизации я сделал чтобы в хэдэре менялись кнопки с вход\регистрация на профиль\выйти
const Header = () => {
const { isAuth, setIsAuth } = useContext(AuthContext);
function SignOut() {
window.location.assign("/main");
AccountService.SignOut();
setIsAuth(false);
}
return (
<header className="p-3 mb-3" style={{ background: "#010A19" }}>
<div className="container">
<div className="d-flex flex-wrap align-items-center justify-content-center justify-content-lg-start">
<Logo />
<HeadLinks />
{isAuth ? (
<div className="px-5 col-md-3 text-end">
<BorderButLink link="/profile" butName="Профиль" />
<FillButton butName="Выйти" func={SignOut} />
</div>
) : (
<div className="px-5 col-md-3 text-end">
<BorderButLink link="/login" butName="Вход" />
<FillButLink link="/register" butName="Регистрация" />
</div>
)}
</div>
</div>
</header>
);
};
export default Header;
Я здесь проверяю через isAuth авторизован пользователь или нет, тут все работает хорошо Далее же я сделал список публичных и приватных роутов
export const publicRoutes = [
{path: '/main', component : <Main/>, exact: true},
{path: '/error', component : <Error/>, exact: true},
{path: '/login', component : <Login/>, exact: true},
{path: '/register', component : <Register/>, exact: true},
{path: '/', component : <Navigate replace to="/main" />, exact: true},
{path: '*', component : <Navigate replace to="/error" />, exact: true},
]
export const privateRoutes = [
...publicRoutes, {path: '/profile', component : <Profile/>, exact: true}
]
И по схеме из хэдэра я указываю какие роуты нужно отрисовывать
const MyRoutes = () => {
const { isAuth } = useContext(AuthContext);
return (
<Routes>
{isAuth
? privateRoutes.map((route) => (
<Route
key={route.path}
path={route.path}
element={route.component}
exact={route.exact}
/>
))
: publicRoutes.map((route) => (
<Route
key={route.path}
path={route.path}
element={route.component}
exact={route.exact}
/>
))}
</Routes>
);
};
export default MyRoutes;
И проблема заключается в том что при авторизации отрисовываются privateRoutes, но страница с профилем недоступна, меня редиректит на страницу с ошибкой
Для проверки авторизован пользователь или нет использовал useState
function App() {
const [isAuth , setIsAuth] = useState(false);
const [userRole, setUserRole] = useState("User");
useEffect(() => {
if (localStorage.getItem("AccessToken") !== null) {
setIsAuth(true)
setUserRole(localStorage.getItem("UserRole"));
}
},[]);
return (
<AuthContext.Provider value={{ isAuth, setIsAuth }}>
<UserRoleContext.Provider value={{ userRole, setUserRole }}>
<Header />
<div
className="container px-4 py-5 mb-5"
style={{ background: "#053566" }}
id="icon-grid"
>
<BrowserRouter>
<MyRoutes/>
</BrowserRouter>
</div>
<Footer />
</UserRoleContext.Provider>
</AuthContext.Provider>
);
}
export default App;
Смотрел несколько видео с подобной реализацией приватных роутов и в видео все работает, где я мог допустить ошибку?
Так как я совсем недавно начал изучать React, еще не совсем понимаю как работает useState, читал что он асинхронный и проблема может быть в этом, но я же использовал useEffect для установки его значения и так же кнопки в хэдэре меняются и там все работает, сижу с этой проблемой несколько дней, надеюсь на помощь
UPD Понял что путь к странице профиля не отрисовывается из за
{path: '*', component : <Navigate replace to="/error" />, exact: true}
Только не понимаю как это пофиксить, если данный роут закомментировать, то при авторизации пользователя все работает, но если на данный путь зайти при не авторизованном пользователе, то страничка просто не рендерится
РЕШЕНИЕ - сработало для меня
const MyRoutes = () => {
const { isAuth } = useContext(AuthContext);
return (
<Routes>
{isAuth
? privateRoutes.map((route) => (
<Route
key={route.path}
path={route.path}
element={route.component}
exact={route.exact}
/>
))
: publicRoutes.map((route) => (
<Route
key={route.path}
path={route.path}
element={route.component}
exact={route.exact}
/>
))}
<Route path="*" element={<Error />} />
<Route path="/" element={<Navigate replace to="/main" />} />
</Routes>
);
};
export default MyRoutes;
Вынес данные пути как общие