React Router V4-组件未在<switch>下呈现

时间:2019-02-15 05:32:10

标签: react-redux react-router react-router-v4

我正在尝试将一组硬编码的<Route />转换为从config变量动态生成的内容。例如

来自

<Router>
    <Switch>
        <Route path="/" component={Home} exact />
        <Route path="/about" component={About} />
        <Route path="/documents" component={Documents} exact />
        <Route path="/documents/faq" component={DocFAQ} />
        <Route path="/documents/translations" component={Translations} />
    </Switch>
</Router>

收件人

const routes = [
    {
        path: '/',
        component: Home,
        exact: true
    },
    {
        path: '/about',
        component: About
    },
    {
        path: '/documents',
        component: Documents,
        children: [
            {
                path: '/faq',
                component: DocFAQ
            },
            {
                path: '/translations',
                component: Translations
            }
        ]
    }
];

const RecursiveRoute = ({ route, parentPath = '' }) => {
    const path = parentPath + route.path;
    return (
        <React.Fragment>
            <Route path={path} exact={route.exact || (route.children != null)} component={route.component} />
            {route.children && route.children.map((childRoute, i) => <RecursiveRoute key={i} route={childRoute} parentPath={path} />)}
        </React.Fragment>
    );
};

const Routes = () => (
    <Router>
        <Switch>
            {routes.map((route, i) => <RecursiveRoute key={i} route={route} />)}
        </Switch>
    </Router>
);

当我在<Router>之外进行映射调用时,此代码将完全生成我想要的;例如。我可以验证其输出的代码与之前的硬编码块完全相同。但是,当它位于<Switch>内时,仅映射routes数组中的第一条路线-不会生成其他任何东西。将日志记录语句放在<RecursiveRoute>中可以确认这一点。

这是为什么,怎么解决?

另一个奇怪的事情是,如果我将<RecursiveRoute>的JSX粘贴到map语句中,它就可以工作(除非在这种情况下我不能使其递归):

<Switch>
    {routes.map((route, i) => <Route key={i} path={route.path} exact={route.exact || (route.children != null)} component={route.component} />)}
</Switch>

但是,如果我将其外包给另一个组件,则映射将再次失败。


[编辑]解决方案:

基于mehamasum's answer,将<RecursiveRoute>从组件更改为函数解决了此问题:

function generateRecursiveRoute(route, parentPath = '') {
    const path = parentPath + route.path;
    const routeHasChildren = (route.children != null);
    const baseHtml = <Route path={path} exact={route.exact || routeHasChildren} component={route.component} key={path} />;
    return !routeHasChildren ?
        baseHtml :
        <React.Fragment key={path}>
            {baseHtml}
            {route.children.map((childRoute) => generateRecursiveRoute(childRoute, path))}
        </React.Fragment>;
}

const Routes = () => (
    <Router>
        <Switch>
            {routes.map((route) => generateRecursiveRoute(route))}
        </Switch>
    </Router>
);

1 个答案:

答案 0 :(得分:1)

Switchimplemented in such a way,您将多个组件作为子组件提供,它将呈现具有匹配的component的第一个组件path。因此,如果您提供的不是Route子项(没有pathcomponent道具的子项),则需要确保在其中编写渲染逻辑。因为Switch不知道该做什么,因为它没有看到与该孩子相关的componentrender道具。

因此,当您直接映射到Route时,它们正在工作,但是当您映射到RecursiveRoute时,它失败了。它上面没有path也没有component,对吧?

我对您的代码做了一些更新,以便将路由直接呈现为Switch的子代:

// refactor of RecursiveRoute to
// use it as an utility function, not as component

const getRecursiveRoute = route => {
  if (route.children) {
    const RootComponent = route.component;
    return (
      <Route
        key={route.path}
        path={route.path}
        render={props => {
          return (
            <React.Fragment>
              {/* render the root matching component*/}
              <RootComponent {...props} />

              {/* render the subroutes */}
              {/* TODO: consider having a Switch here too */}

              {route.children.map(route =>
                getRecursiveRoute({
                  ...route,
                  path: props.match.url + route.path
                })
              )}
            </React.Fragment>
          );
        }}
      />
    );
  }
  return (
    <Route
      key={route.path}
      path={route.path}
      exact={route.exact || route.children != null}
      component={route.component}
    />
  );
};

const Routes = () => {
  return (
    <Router>
      <Switch>{routes.map(route => getRecursiveRoute(route))}</Switch>
    </Router>
  );
};

Edit x2kx286x44

您可能必须修复一些有关精确路由的极端情况。希望对您有所帮助。