react-router重定向不会更改Switch

时间:2019-08-24 04:28:16

标签: reactjs typescript react-router-v4

我正在使用react-router设置我的应用程序,并尝试使用<Redirect/>设置用于身份验证的路由器。

Route组件具有两个不同的组件,一个是private Route,另一个是public route

预期结果:当auth为false时,页面应跳回到我设置为<Redirect to={"/public"} />的公共页面 到目前为止,路由似乎工作正常,但重定向无法正常工作。 任何想法都欢迎!谢谢!

PrivateRoute

interface PrivateRouteProps {
  isLogin: boolean;
  privateRoutes: RouteItem[];
}

const PrivateRoute: React.FunctionComponent<PrivateRouteProps> = (
  props: PrivateRouteProps
) => {
  return (
    <>
      {props.isLogin ? (
        props.privateRoutes.map(item => {
          return <Route key={item.path} {...item} />;
        })
      ) : (
        <Redirect to={PUBLIC.path} />
      )}
    </>
  );
};

PublicRoute

interface PublicProps {
  publicRoutes: RouteItem[];
}

const PublicRoute: React.FC<PublicProps> = (props: PublicProps) => {
  return (
    <>
      {props.publicRoutes.map(route => (
        <Route key={route.path} {...route} />
      ))}
    </>
  );
};

Route

<BrowserRouter>
      <Switch>
        <PublicRoute publicRoutes={publicRoutes} />
        <PrivateRoute privateRoutes={privateRoutes} isLogin={login} />
      </Switch>
    </BrowserRouter>

更新 正如公认的答案所述,<Switch/>完全与Fragment配合使用,因此我按照以下方式修改了路线,它的作用就像是一种魅力。 只是更新它,以便有人可能有类似的问题。

<BrowserRouter>

            <Switch>
                {publicRoutes.map(item => {
                    return <Route key={item.path} {...item}/>
                })}
                {privateRoutes.map(item => {
                    return <PrivateRoute key={item.path}
                                         exact={item.exact}
                                         component={item.component}
                                         path={item.path}
                                         redirectPath={SIGN_IN.path}
                    />

      })}
            </Switch>
        </BrowserRouter>

1 个答案:

答案 0 :(得分:2)

我遍历了您的代码,归结为一件事。组件<Switch>与片段<></>一起工作的方式。它只寻找第一个React Fragment,因为他们不想横穿一棵树:

https://github.com/ReactTraining/react-router/issues/5785

要解决此问题,您需要删除组件内部的React.Fragment。 因此您的应用程序将如下所示:

<Switch> 
    <Route ...>
    <Route ...>
    <Route ...>
</Switch>

(现在是 btw

      <Switch> 
    //it will only sees the first one //if you switch orders - Private with Public
    // Private will work but not Public anymore :(
        <React.Fragment>
            <Route ...>
            <Route ...>
        </React.Fragment>
        <React.Fragment>
            <Route ...>
        </React.Fragment>
     </Switch>

另一种解决方案(这是我做的,因为我不熟悉TypeScript,不足以更改类型和返回值)是在您的switch应用程序中添加 wrapper 并处理private的返回在<Route>内部使用render方法进行路由,如下所示:

  //index.tsx
        <Switch>
            <>
            <PublicRoute publicRoutes={publicRoutes}/>
            <PrivateRoute privateRoutes={privateRoutes} isLogin={login}/>
            </>
        </Switch>

这会导致另一个错误,即无限循环重新渲染(同样,react-router很可能是 使用嵌套路由的时间很差),并解决了对私有路由执行以下操作组件:

  //PrivateRoute.tsx
return (
    <>
        {props.privateRoutes.map(item =>
            <Route key={item.path} exact path={item.path} render={() => (
                !props.isLogin
                    ? (
                    <Redirect to={PUBLIC.path}/>
                ):
                    //HOC transforming function Component into Component
                    // @ts-ignore (you can deal here better than me hehehe)
                    ((PrivateComponent)=><PrivateComponent/>)(item.component)
            )}/>)}
    </>
);

TL,DR:您正在通过在结构内部添加<></>(转换为 React.Fragment )来增加嵌套的复杂性。如果您删除它们或按照上面的代码操作,应该没问题

希望我对您有所帮助。祝好运! :)