Как сделать роутинг при помощи массива объектов?(react-router-dom)
Всем привет. Не так давно я смотрел видео про то, как пользоваться firestore используя react(вот ссылка, если кому интересно: https://www.youtube.com/watch?v=12kgyxvsxUs&t=581s). Там я увидел клевый вариант роутинга при помощи массива объектов. Смысл в том, что есть два массива: публичные и приватные роуты. А в этих массивах находятся объекты со свойствами: path и component. Потом мы создаем компонент, который берет один из таких массивов и при помощи map делает из него массив роутов, а в конце мы прибавляем редирект для несуществующих путей. Вот примерно то, как это выглядит:
export const publicRoutes = [
{
path: HOME_ROUTE,
component: Home,
},
{
path: LOGIN_ROUTE,
component: Login,
}
];
export const privateRoutes = [
{
path: PROFILE_ROUTE,
component: Profile,
}
];
const AppRouter = ({routesArr, redirectPath = '/'}) => {
return (
<Switch>
{routesArr.map(({path, component}) =>
<Route key={path} path={path} component={component} exact={true}/>
)}
<Redirect to={redirectPath}/>
</Switch>
);
};
Проблема же состоит в том, что в видео автор использует публичные пути, когда пользователь только не авторизован, если пользователь авторизуется, то он использует только приватные роуты. Я же хочу сделать так, чтобы публичные роуты были доступны в любом из этих случаев. Но из-за редиректов получается так, что я не могу это сделать. Т.к. если я вставляю компонент с публичными роутами всегда и хочу зайти на какую-то приватную страницу сайта будучи авторизованным, то при рендере все равно срабатывает редирект публичных роутов и просто не дает мне этого сделать. Аналогичная ситуация происходит, если я меняю местами компоненты с публичными и приватными роутами.
const App = () => {
let [isAuth, setIsAuth] = useState(false);
return (
<BrowserRouter>
isAuth: {isAuth ? 'true': 'false'}
<button onClick={() => setIsAuth(!isAuth)}>change isAuth</button>
<Header/>
<AppRouter routesArr={publicRoutes}/>
{isAuth && <AppRouter routesArr={privateRoutes} redirectPath={PROFILE_ROUTE}/>}
</BrowserRouter>
);
}
Возможно, кто-то знает, как реализовать примерно такую же функциональность, не вставляя в код кучу костылей?)
Ответы (1 шт):
Всем снова привет) В общем, я тут еще немного подумал и кое-что придумал. Теперь у нас есть не массивы с публичными и приватными роутами, а один амссив со всеми роутами. Но только теперь эти роуты в массиве можно настраивать) Я добавил свойство withAuth, которое как раз и отвечает за то, будет ли этот путь приватным или нет. Так же я написал hoc, которая принимает другую компоненту и проверяет, авторизован пользователь или нет. Вот код реализации:
export const appRoutes = [
{
path: HOME_ROUTE,
Component: Home,
exact: true,
},
{
path: LOGIN_ROUTE,
Component: Login,
},
{
path: PROFILE_ROUTE,
Component: Profile,
withAuth: true,
}
];
const AppRouter = () => {
return (
<Switch>
{appRoutes.map(({path, Component, exact, withAuth}) => {
if (withAuth) {
return <Route path={path} exact={exact} component={withAuthRedirect(Component)}/>
}
return <Route path={path} exact={exact} component={Component}/>
})}
<Redirect to={HOME_ROUTE}/>
</Switch>
);
};
const App = ({isAuth, login_user, logout_user}) => {
return (
<BrowserRouter>
isAuth: {isAuth ? 'true': 'false'}
<button onClick={login_user}>login</button>
<button onClick={logout_user}>logout</button>
<div>
<NavLink to={PROFILE_ROUTE}>Profile</NavLink>
</div>
<Header/>
<AppRouter />
</BrowserRouter>
);
}
Единственное, у меня немного вызывает сомнение мой вызов withAuthRedirect, корректно ли так делать?