将React路线组织到单独的组件中

时间:2019-09-28 08:36:04

标签: javascript reactjs react-router

我正试图找到一种方法来组织路线,以帮助将来可能接管我工作的开发人员。我想到了将<Route />条目分成单独的组件,然后将其加载到类似于为用户分配组的主要组件中。

问题是,当使用多个组件时,只有第一个组件有效。这可能不是这样做的最大反应方式,所以我也乐于接受其他选择。

原始路线安排

const AllRoutes = () => {
    return (
        <Switch>
            {/* public routes*/}
            <Route path={'/about'} component={AboutView} />
            <Route path={'/project'} component={ProjectView} />
            <Route path={'/contact'} component={ContactView} />

            {/* auth routes */}
            <Route path={'/login'} component={LoginView} />
            <Route path={'/logout'} component={LogoutView} />

            <Route component={Error404View} />
        </Switch>
    )
}

将公共路线与授权路线分开:

const PublicRouteGroup = () => {
    return (
        <>
            <Route path={'/about'} component={AboutView} />
            <Route path={'/project'} component={ProjectView} />
            <Route path={'/contact'} component={ContactView} />
        </>
    )
}

const AuthRouteGroup = () => {
    return (
        <>
            <Route path={'/login'} component={LoginView} />
            <Route path={'/logout'} component={LogoutView} />
        </>
    )
}

这样,我可以这样使用它:

const AllRoutes = () => {
    return (
        <Switch>
            <PublicRouteGroup />    {/* This works */}
            <AuthRouteGroup />      {/* This doesn't */}


            {/* This 404 is not a route group */}
            <Route component={Error404View} />
        </Switch>
    )
}

翻转<PublicRouteGroup /><AuthRouteGroup />仅更改顺序:

const AllRoutes = () => {
    return (
        <Switch>
            <AuthRouteGroup />      {/* This works */}
            <PublicRouteGroup />    {/* This doesn't */}

            {/* This 404 is not a route group */}
            <Route component={Error404View} />
        </Switch>
    )
}

希望您对此有任何想法。

更新#1:

这要感谢@skyboyer。通过将<Switch>移动到子组件并将其从AllRoutes组件中删除,每个组件开始显示。看来在<Switch>中添加AllRoutes仅允许显示第一个匹配项,与<Switch>一样。但是现在通过删除它,它也在每页末尾显示了404。

基本上,它看起来像这样:

const AllRoutes = () => {
    return (
        <>
            <Route component={AuthRouteGroup} />      {/* This works */}
            <Route component={PublicRouteGroup} />    {/* This also works */}

            {/* This 404 is not a route group */}
            <Route component={Error404View} />        {/* Always shown at the bottom */}
            {/* Even putting the 404 in its own RouteGroup yields the same issue */}
        </>
    )
}

2 个答案:

答案 0 :(得分:0)

在顶层没有Swtich的情况下

  <Route component={PublicRouteGroup} />
  <Route component={AuthRouteGroup} />      

因此它们是无条件渲染的。然后在组件中添加额外的Switch,例如


const AuthRouteGroup = () => {
    return (
        <Switch>
            <Route path={'/login'} component={LoginView} />
            <Route path={'/logout'} component={LogoutView} />
        <Switch/>
    )
}

但是为什么id无效?

原因是how Switch works

React.Children.forEach(this.props.children, child => {
  if (match == null && React.isValidElement(child)) {
    element = child;
    const path = child.props.path || child.props.from;

    match = path
      ? matchPath(location.pathname, { ...child.props, path })
      : context.match;
  }
});

请注意,即使AuthRouteGroup不是RouteSwitch还是会寻找其props.path。并且undefined的{​​{1}}匹配任何路径,并且 props.path仅渲染第一个匹配的Switch时,您将只渲染第一个组件。

[UPD]“不匹配任何路线”视图仅在Route的顶层起作用。而且也没有办法知道兄弟元素的一些嵌套子代是否与当前路径匹配。因此,我所看到的唯一方法是将所有路线都列在一个地方。

看上去很差的替代方法是使用特殊的路由“ / error404”,并将用户从其他组件内部重定向到该路由(但谁来决定?何时何地?何时?)。

答案 1 :(得分:0)

看来,当前可以处理的组件(如OOP类)的设置是错误的方法。相反,我使用了数组,因为这些可以由散布运算符执行。它仍然实现了我所追求的在无数个组中组织路由的相同目标。

为每个组创建阵列

const public_route_group = [
    {path: '/about', component: AboutView},
    {path: '/project', component: ProjectView},
    {path: '/contact', component: ContactView},
]

const auth_route_group = [
    {path: '/login', component: LoginView},
    {path: '/logout', component: LogoutView},
]

const error_route_group = [
    {component: Error404View}   // No path required
]

const user_routes = [
    ...public_route_group,
    ...auth_route_group,
    ...error_route_group
]

创建路线

const AllRoutes = () => {
    return (
        <Switch>
            {user_routes.map((route, idx) => {
                return <Route key={idx} {...route} />
            })}
        </Switch>
    )
}

我认为如果您在数组中使用嵌套对象,也可以对其进行进一步修改。

我要感谢@skyboyer对这个问题的见解。