React Router - являются ли вложенные компоненты <Switch> антишаблоном?

Из документов React Router:

Все дети <Switch> должно быть <Route> или же <Redirect> элементы. Будет отображен только первый дочерний элемент, соответствующий текущему местоположению.

Тем не менее, вложенный <Switch> Заявления разрешены. Я использую шаблон, чтобы разбить большое количество <Routes>:

<Switch>
  <Route path="/foo" component={FooRouter} />
  <Route path="/bar" component={BarRouter} />
  <Route path="/baz" component={BazRouter} />
</Switch>

...

const FooRouter = () => (
  <Switch>
    <Route exact path="/foo/:id" component={ViewFoo} />
    <Route exact path="/foo/new" component={NewFoo} />
  </Switch>
)

const BarRouter = () => (
  <Switch>
    <Route exact path="/bar/new" component={NewBar} />
  </Switch>
)

....

Любопытно, есть ли лучший способ разбить большое количество маршрутов и если они вложены <Switch> высказываний следует избегать?

3 ответа

Nesting <Switch> statements makes the component tree look like this. It unnecessary to make the tree more complicated and it might make debugging harder.

You could modify your existing code to flatten out the nesting by modifying them slightly like this:

const FooRouter = () => (
  [
    <Route exact path="/foo/new" component={NewFoo} key={1} />,
    <Route exact path="/foo/:id" component={ViewFoo} key={2} />
  ]
);

const BarRouter = () => (
  <Route exact path="/bar/new" component={NewBar} />
);

...

<Switch>
  {FooRouter()}
  {BarRouter()}
  <Route path="/baz" component={BazRouter} />
</Switch>

Returning an array of routes flattens out the <Switch> statement however the downside to this is that you'll have to add the key prop to prevent React from throwing a warning.

Поскольку вы решаете это просто отлично, когда у вас много вложенных маршрутов, вы можете протянуть их через приложение и сделать динамические маршруты, но вскоре выйдет response-router-dom v6 с огромным обновлением, одним из них является useRoutes, который позволяет вам настраивать ваши маршруты такие:

let element = useRoutes([
    // A route object has the same properties as a <Route>
    // element. The `children` is just an array of child routes.
    { path: '/', element: <Home /> },
    {
      path: 'users',
      element: <Users />,
      children: [
        { path: '/', element: <UsersIndex /> },
        { path: ':id', element: <UserProfile /> },
        { path: 'me', element: <OwnUserProfile /> },
      ]
    }
  ]);

введение в response-router-dom v6 у них есть классная новая функция, на которую стоит обратить внимание, одна из них - это замена на witch, которая поможет вам много с вложенными маршрутами и забавной вещью, которую вам больше не нужно использовать

     <Routes>
        <Route path="/" element={<UsersIndex />} />
        <Route path=":id" element={<UserProfile />} />
        <Route path="me" element={<OwnUserProfile />} />
      </Routes>

вот как это будет выглядеть с новой функцией

Примечание о вложенных условных маршрутах: Switch должен иметь только потомков Route. Если вы объявите Switch внутри Switch, каждый маршрут после Switch не будет использоваться, т.е.

      <Switch>
  <Route path="/1" />
  <Switch> ... </Switch>
  <Route path="/2" /> // this one won't work!
</Switch>

Так что не делайте этого, придерживайтесь объявления одного маршрута для каждого условия или отображайте маршруты в виде массива при общем условии:

      <Switch>
  {condition && <Route path="/1" >}
  {condition && <Route path="/2">}
  {/* or */}
  {anotherCondition && [
    // notice `key`. React will warn you about rendering a list without key prop
    <Route key="3" path="/3">,
    <Route key="4" path="/4">,
  ]}
</Switch>

Это верно для react-router-dom v5, не уверен насчет 6.

Другие вопросы по тегам