Reacjs递归函数

时间:2018-12-11 16:37:54

标签: reactjs react-router

我已经创建了一个函数,并且视情况而定,我想调用相同的函数

 buildRoute(listRoutes){
    return(
      <Switch>
        {listRoutes.map((prop, key) => {
          if(prop.subMenus != null){
            if(prop.path !== undefined){
              return
                this.routes(prop, key);
                this.buildRoute(prop.subMenus);
            }else{
              return this.buildRoute(prop.subMenus);
            }
          }else{
            return this.routes(prop, key);
          }
        })}
      </Switch>
    )
  }

  routes(prop, key){
    if (prop.redirect){  
      return <Redirect from={prop.path} to={prop.to} key={key} />;
    }else if(prop.private){        
      return <PrivateRoute authenticated={JSON.parse(localStorage.getItem(IS_AUTHENTICATED))} path={prop.path} component={prop.component} key={key} />;
    }else{
      return <Route path={prop.path} component={prop.component} key={key} />;
    }
  }

但是我有这个错误: VM3056 53.chunk.js:89036警告:数组或迭代器中的每个子代都应具有唯一的“键”道具。

检查APP的渲染方法。     在Switch中(在Dashboard.jsx:84)     在APP中(由WithStyles(APP)创建)     在WithStyles(APP)中(由Route创建)     在Route中(在src / index.js:46处)     在Switch(在src / index.js:42)     在路由器中(位于src / index.js:41)     在I18nextProvider中(位于src / index.js:40)

我的列表路线:

        const dashboardRoutes = [
      {
        private: true,
        path: "/private/dashboard",
        sidebarName: "menu.sidebarName.dashboard",
        navbarName: "header.navbarName.dashboard",
        icon: Dashboard,
        component: DashboardPage
      },
      {
        private: true,
        path: "/private/MENU1",
        navbarName: "header.navbarName.MENU1",
        component: MENU1,
        sidebarName: "menu.sidebarName.MENU1",
        code: "MENU1",
        icon: "content_paste",
        subMenus:[
          {
        subMenu: true,
        private: true,
        path: "/private/MENU1_SOUS_MENU1",
        sidebarName: "menu.sidebarName.MENU1_SOUS_MENU1",
        navbarName: "header.navbarName.MENU1_SOUS_MENU1",
        code: "MENU1_SOUS_MENU1",
        icon: "content_paste",
        component: MENU1_SOUS_MENU1
      },
      {
        subMenu: true,
        private: true,
        path: "/private/MENU1_SOUS_MENU2",
        sidebarName: "menu.sidebarName.MENU1_SOUS_MENU2",
        navbarName: "header.navbarName.MENU1_SOUS_MENU2",
        code: "MENU1_SOUS_MENU2",
        icon: "content_paste",
        component: MENU1_SOUS_MENU2
      }
    ]
   },
   {
        sidebarName: "menu.sidebarName.MENU12",
        code: "MENU12,
        icon: "content_paste",
        subMenus:[
          {
        subMenu: true,
        private: true,
        path: "/private/MENU2_SOUS_MENU1",
        sidebarName: "menu.sidebarName.MENU2_SOUS_MENU1",
        navbarName: "header.navbarName.MENU2_SOUS_MENU1",
        code: "MENU2_SOUS_MENU1",
        icon: "content_paste",
        component: MENU2_SOUS_MENU1
      },
      {
        subMenu: true,
        private: true,
        path: "/private/MENU2_SOUS_MENU2",
        sidebarName: "menu.sidebarName.MENU2_SOUS_MENU2",
        navbarName: "header.navbarName.MENU2_SOUS_MENU2",
        code: "MENU2_SOUS_MENU2",
        icon: "content_paste",
        component: MENU2_SOUS_MENU2
      }
    ]
  },
   .....
  { 
    redirect: true, 
    path: "/private", 
    to: "/private/dashboard"
  }
  ]

3 个答案:

答案 0 :(得分:1)

问题是您的buildRoute可以返回一个Route或另一个Switch。不过,您的Switch组件没有密钥。

您也有

if(prop.path !== undefined){
          return
            this.routes(prop, key);
            this.buildRoute(prop.subMenus);
        }

这实际上什么也不会返回。并且即使您将this.routesreturn移到同一行,它也只会返回该行,并且永远不会调用this.buildRoute(prop.subMenus);。您应该返回一个包含两个元素的数组。

所有修复在一起(注意,我正在更改buildRoute的签名以接受其他参数

buildRoute(listRoutes) {
    return (
        {listRoutes.map((prop, key) => {
          if (prop.subMenus != null) {
            if (prop.path !== undefined) {
              return [
                this.routes(prop, key),
                this.buildRoute(prop.subMenus)
              ];
            } else {
              return this.buildRoute(prop.subMenus);
            }
          } else {
            return this.routes(prop, key);
          }
        })}
    );
  }
  
render(){
  return <Switch>{this.buildRoute(dashboardRoutes)}</Switch>;
}


需要进一步注意的是,您不能嵌套Switch个元素(请参阅https://github.com/ReactTraining/react-router/issues/6199 )。

因此,请删除嵌套Switch并将buildRoute的结果包装在单个Switch

演示在https://codesandbox.io/s/ppwk4qnrox

答案 1 :(得分:0)

该错误仅是因为您在通过listRoutes映射时未指定键。您不会在此处的代码中显示this.routes方法。但是我想这是您返回JSX元素的地方。因此,您应该在其中设置一个密钥。您已经传递了密钥,因此,如果没有更好的选择,请使用该密钥。

答案 2 :(得分:0)

您需要克隆element,以便实际上可以将其传递给密钥。将键传递给子功能不起作用AFAIK。

buildRoute (listRoutes) {
  return (
    <Switch>
      {listRoutes.map((prop, key) => {
        if (prop.subMenus != null) {
          if (prop.path != null) {
            return React.cloneElement([
              this.routes(prop),
              this.buildRoute(prop.subMenus)
            ], { key });
          } else {
            return React.cloneElement(this.buildRoute(prop.subMenus), { key })
          }
        } else {
          return React.cloneElement(this.routes(prop), { key });
        }
      })}
    </Switch>
  )
}

然后,您可以从key函数中删除routes参数。另外,请删除key={key}中的return

另一种解决方案是将所有内容包装到设置了密钥的“包装器”中。

buildRouteItem (prop) {
  if (prop.subMenus != null) {
    if (prop.path != null) {
      return [
        this.routes(prop),
        this.buildRoute(prop.subMenus)
      ]
    } else {
      return this.buildRoute(prop.subMenus);
    }
  } else {
    return this.routes(prop);
  }
}

buildRoute (listRoutes) {
  return (
    <Switch>
      {listRoutes.map((prop, key) => (
        <div key={key}>
          {this.buildRouteItem(prop)}
        </div>
      ))}
    </Switch>
  )
}
相关问题