【问题标题】:React Router V4 - Components not rendering under <Switch>React Router V4 - 组件未在 <Switch> 下呈现
【发布时间】:2019-02-15 05:32:09
【问题描述】:

我正在尝试将硬编码的&lt;Route /&gt;s 块转换为从配置变量动态生成的东西。例如。

来自

<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>
);

当我在&lt;Router&gt; 之外进行映射调用时,此代码会生成我想要的内容;例如。我可以验证它输出的代码与之前的硬编码块完全相同。然而,当它在&lt;Switch&gt; 内时,只有routes 数组中的第一条路由被映射——不会生成其他任何东西。将日志语句放入 &lt;RecursiveRoute&gt; 可以确认这一点。

为什么会这样,我该如何解决?

另一个奇怪的事情是,如果我将 &lt;RecursiveRoute&gt; 的 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,将&lt;RecursiveRoute&gt;从组件改为函数解决了这个问题:

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>
);

【问题讨论】:

  • “映射失败”是什么意思?抛出了某种错误?
  • 就像“只有路由数组中的第一条路由被映射——没有其他的生成”。所以在这个例子中,只生成了 Home 路由。

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


【解决方案1】:

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

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

我已经稍微更新了您的代码,以便将路由直接呈现为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>
  );
};

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

【讨论】:

  • 现在说得通了,谢谢!我发现只需将 &lt;RecursiveRoute&gt; 更改为函数(例如,不使用渲染)也可以正常工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-27
  • 1970-01-01
  • 1970-01-01
  • 2017-07-25
  • 2021-08-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多