Я пытаюсь построить абстракцию вокруг @reach/router
, которая должна обрабатывать аутентификацию в моем приложении. Мне нравится делать следующее:
<Router>
// by default, each route should be protected
<ProtectedComponent path="/protected-path" />
// if you want to route to be public, you should explicitly set it on the route
<PublicComponent path="/this-is-public" isPublic />
</Router>
Я явно не хочу оборачивать каждый компонент чем-то вроде withAuthentication
HO C, потому что большинство маршрутов в моем приложении являются частными.
Я подошел, пытаясь создать свой собственный Router
, который сейчас выглядит так:
import React, { useContext, useEffect } from "react";
import { Router as ReachRouter, RouterProps, useLocation, RouteComponentProps } from "@reach/router";
import { PublicRouteComponentProps } from "../Common/Types/PublicRouteComponentProps";
import { AuthenticationContext } from "@Common/Context/AuthenticationContext";
// idea - all routes are authorized by default. public routes must be explicitly set
interface Props extends RouterProps {
children: React.ReactElement<PublicRouteComponentProps> | React.ReactElement<PublicRouteComponentProps>[];
}
export const Router: React.FC<Props> = ({ children, ...props }) => {
return (
<ReachRouter {...props}>
{React.Children.map(children, (Child: React.ReactElement<PublicRouteComponentProps>) => {
if (Child.props.isPublic) {
return Child;
}
return <WithAuthentication {...Child.props}>{Child}</WithAuthentication>;
})}
</ReachRouter>
)
}
interface AuthProps extends RouteComponentProps {}
const WithAuthentication = ({ children, ...props }) => {
const { isAuthenticated, login } = useContext(AuthenticationContext)
const location = useLocation();
useEffect(() => {
if (!isAuthenticated) {
login({ redirect: location.pathname });
}
}, [isAuthenticated])
return (
<React.Fragment>
<h1>This is a test </h1>
{children}
</React.Fragment>
)
}
Что работает:
- Если вы попадаете на защищенный маршрут, без входа в систему, вы перенаправляетесь на вход
- После входа в систему можно получить доступ к защищенному маршруту
Что не работает:
- К сожалению, визуализируется только элемент
<h1>This is a test </h1>
, но элемент children
не отображается вообще.
Мне кажется, что это как-то связано с дочерними элементами, являющимися фактическим экземпляром (React.Element), а не компонентом.
Есть ли у кого-нибудь идея, почему children
не отображается в этом случае? Возможно ли то, чего я пытаюсь достичь?
Заранее спасибо!