Reacjs рекурсивная функция - PullRequest
       3

Reacjs рекурсивная функция

0 голосов
/ 11 декабря 2018

Я создал функцию и, в зависимости от случая, я хочу вызвать ту же функцию

 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 Предупреждение: каждый ребенок вмассив или итератор должен иметь уникальную опору «key».

Проверьте метод рендеринга APP.в Switch (в Dashboard.jsx: 84) в APP (создан WithStyles (APP)) в WithStyles (APP) (создан Route) в Route (в src / index.js: 46) в Switch (в src / index.js: 42) в Router (в src / index.js: 41) в I18следующий провайдер (в src / index.js: 40)

Мой списокRoute:

        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 голосов
/ 11 декабря 2018

Проблема в том, что ваш buildRoute может либо вернуть Route, либо другой Switch.У ваших Switch компонентов нет ключа.

Также у вас есть

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

, это на самом деле ничего не даст.И даже если вы переместите this.routes в одну строку с return, он только вернет это, и 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

0 голосов
/ 11 декабря 2018

Вам нужно клонировать элемент, чтобы вы могли передать ему ключ.Передача ключа дочерней функции не работает 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>
  )
}
0 голосов
/ 11 декабря 2018

Эта ошибка только потому, что вы не указали ключ при отображении через listRoutes.Вы не показываете метод this.routes в своем коде здесь.Но я думаю, это то, что вы возвращаете свой элемент JSX.Таким образом, вы должны установить ключ там.Вы уже передаете ключ, поэтому просто используйте его, если у вас нет лучшего выбора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...