首页 > 解决方案 > 基于动态上下文值的 React Router

问题描述

我希望你一切都好。

我正在开发一个 react(typescript) 应用程序,我必须在其中处理身份验证和授权。

我正在遵循这种模式。IAuthContext(将在启动期间或用户更改其状态时加载)

export interface IAuthContext {
    isAuthenticated: boolean;
    isInitialized: boolean;
    user: firebase.User | null;
    permissions: object;
    landingPage: string;
    isOnBoardingCompleted: boolean;
}

路由.js

const routerConfig = [
    {
        key: "key_",
        path: '/login',
        component: Login,
        isPrivate : false
    },
    {
        key: "dashboard",
        path: '/dashboard',
        component: Frame,
        content: AnalyticsDashBoard,
        isPrivate : true
    },

应用程序.tsx

return (
        <BrowserRouter>
            <div>
                <Switch>
                    {routes.map((route) =>{
                        return (route.isPrivate ?
                            <PrivateRoute {...route} exact/>
                            :
                            <Route path={route.path} component={route.component} key={route.key} exact/>)
                    })}
                </Switch>
            </div>
        </BrowserRouter>
    );

PrivateRoute.tsx

return (
        <Route
            {...rest}
            render={(routeProps) =>
                props.context.isAuthenticated ? (
                    <Component {...routeProps} content={props.content}/>
                ) : (
                    <Redirect
                        to={{
                            pathname: '/login',
                            state: { from: routeProps.location }
                        }}
                    />
                )
            }
        />
    );

在 privateRoute 我可以访问角色和权限以及登录页面(如果用户在登录后没有完成注册,他必须被重定向到注册页面)。此外,我需要根据身份验证在私有路由中提供所有可能的组合,因为它只会加载一次。

我试图在私人路线上这样做

if (props.context.isAuthenticated && !props.context.isOnBoardingCompleted) {
        console.log("Going to redirect here to onboard--", props.context.landingPage);
        return <Route path={props.context.landingPage} component={OnBoarding}/>
    }

但这不起作用,因为只有 URL 发生了变化。此外,如果用户完成了入职操作,我可能没有路由,因为所有路由器控件都已使用首次值创建。请告诉我如何处理这个问题?我需要做的就是拥有某种拦截器,在其中我根据动态上下文值路由/重定向到页面。

期望:就像上面的场景一样,有多个角色和权限,所有这些条件都应该在这里检查。

标签: reactjstypescriptreact-router

解决方案


<Route path={props.context.landingPage} component={OnBoarding}/>应该在你的Router组件中定义。

您可以使用嵌套的三元组,但这会导致可读性问题。

return (
  <Route
    {...rest}
    render={routeProps =>
      props.context.isAuthenticated ? (
        props.context.isOnBoardingCompleted ? (
          <Component {...routeProps} content={props.content} />
        ) : (
          <Redirect
            to={{
              pathname: "/landing", // or "/onboard" whatever the route is
              state: { from: routeProps.location }
            }}
          />
        )
      ) : (
        <Redirect
          to={{
            pathname: "/login",
            state: { from: routeProps.location }
          }}
        />
      )
    }
  />
);

推荐阅读