Вложенные маршруты в React Router v4

Я пытаюсь настроить несколько вложенных маршрутов, чтобы добавить общий макет. Проверьте код:

  <Router>
    <Route component={Layout}>
      <div>
        <Route path='/abc' component={ABC} />
        <Route path='/xyz' component={XYZ} />
      </div>
    </Route>
  </Router>

Хотя это работает отлично, я все равно получаю предупреждение:

Предупреждение: Вы не должны использовать ‹Компонент маршрута› и ‹Дочерний маршрут› в одном и том же маршруте; будет игнорироваться


person Sean Gillespie    schedule 07.02.2017    source источник
comment
Возможный дубликат вложенных маршрутов с реагирующим маршрутизатором v4   -  person Pio    schedule 09.04.2017


Ответы (5)


Ответ CESCO сначала отображает компонент AppShell, затем один из компонентов внутри Switch. Но эти компоненты НЕ будут отображаться внутри AppShell, они НЕ будут дочерними элементами AppShell.

В версии 4, чтобы обернуть компоненты, которые вы больше не кладете Route внутри другого Route, вы помещаете свои Route непосредственно внутрь компонента.
Т.е.: для оболочки вместо <Route component={Layout}> вы напрямую используете <Layout>.

Полный код:

  <Router>
    <Layout>
      <Route path='/abc' component={ABC} />
      <Route path='/xyz' component={XYZ} />
    </Layout>
  </Router>

Это изменение, вероятно, объясняется идеей сделать React Router v4 чистым React, чтобы вы использовали только элементы React, как и любой другой элемент React.

РЕДАКТИРОВАТЬ: я удалил компонент Switch, так как он здесь бесполезен. Узнайте, когда это будет полезно здесь.

person Ilan Schemoul    schedule 10.03.2017
comment
Спасибо! Обернув это так: <Layout><Switch><Route/></Switch></Layout> сработало для меня :) - person protoEvangelion; 12.03.2017
comment
Без проблем. Если вы используете один Route, вам НЕ нужен Switch. Switch похож на || оператор: первый Route внутри оператора Switch, который соответствует пути, отображается, но другие Route внутри Switch НЕ отображаются. Я добавил ссылку на документ Switch в свой комментарий. - person Ilan Schemoul; 12.03.2017
comment
Спасибо, это очень полезно. - person slorenzo; 08.04.2017
comment
Отличное решение. я - person MLhacker; 02.06.2017
comment
Спасибо, это помогло мне лучше понять и решить проблему. - person Jaime Rios; 14.10.2017
comment
что, если вам нужен еще один элемент Route, который НЕ обернут макетом? Сегодня я весь день пытаюсь заставить его работать и не могу найти правильный путь (пример: ABC, XYZ — это страницы после входа в систему, поэтому им нужен макет, который содержит боковую панель, меню и т. д., но вам также нужен маршрут для страница входа, которая не нуждается в меню) - person Kamil Mikolajczyk; 17.10.2017
comment
Как можно получить объект location или location.pathname внутри компонента макета (т.е. this.props.location.pathname)? - person Ibro; 08.01.2018
comment
Почему это не общеизвестно! (Возможно, это сейчас, но все же пришлось изрядно поискать, чтобы найти) - спасибо, сэр. - person Jamie; 04.07.2018

Вам нужно использовать компонент переключения для вложения, чтобы работать хорошо. Также см. этот вопрос

// main app
<div>
    // not setting a path prop, makes this always render
    <Route component={AppShell}/>
    <Switch>
        <Route exact path="/" component={Login}/>
        <Route path="/dashboard" component={AsyncDashboard(userAgent)}/>
        <Route component={NoMatch}/>
    </Switch>
</div>

Компоненты версии 4 не берут дочерние элементы, вместо этого вы должны использовать свойство рендеринга.

<Router>
    <Route render={(props)=>{
      return <div>Whatever</div>}>
    </Route>
  </Router>
person CESCO    schedule 16.02.2017

Пытаться:

<Router>
    <Layout>
        <Route path='/abc' component={ABC} />
        <Route path='/xyz' component={XYZ} />
    </Layout>
</Router>
person marrekk    schedule 01.03.2017
comment
Когда вы добавляете ответ, добавьте какое-то объяснение, чтобы оно было полезно для других. Однако +1 за ответ на него первым - person Shubham Khatri; 27.05.2017
comment
Не полезный комментарий. Пример не всегда помогает. - person Yagiz; 29.06.2017
comment
Кажется, это работает и с BrowserRouter вместо Router. - person Jimmy Adaro; 20.03.2019

Если вы не хотите, чтобы Layout запускался при загрузке. Используйте этот метод:

<div className="container">
    <Route path="/main" component={ChatList}/>
    <Switch>
        <Route exact path="/" component={Start} />
        <Route path="/main/single" component={SingleChat} />
        <Route path="/main/group" component={GroupChat} />
        <Route path="/login" component={Login} />
    </Switch>
</div>

Всякий раз, когда история изменяется, componentWillReceiveProps в ChatList будет запущен.

person Avare Kodcu    schedule 21.08.2017

Вы также можете попробовать это:

<Route exact path="/Home"
                 render={props=>(
                                 <div>
                                      <Layout/>
                                      <Archive/>
                                </div>
                       )} 
    />
person Mohamed Yahya    schedule 31.12.2017