Как обернуть экземпляр React.Children - PullRequest
0 голосов
/ 06 августа 2020

Я пытаюсь построить абстракцию вокруг @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 не отображается в этом случае? Возможно ли то, чего я пытаюсь достичь?

Заранее спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...