Подтвердить что ты не робот

Использование React-Router с страницей макета или несколькими компонентами на странице

Я добавляю к маршрутизатору новый маршрутизатор.

В настоящее время модель передается корневому компоненту, который содержит компонент навигации для суб-навигации и основной компонент.

В примерах реагирующего маршрутизатора я обнаружил, что у меня есть только один дочерний компонент, что лучший способ изменить несколько дочерних компонентов, не повторяя код макета в обоих?

4b9b3361

Ответ 1

Если вы правильно поняли, чтобы достичь этого, вы должны определить несколько компонентов в Route. Вы можете использовать его как:

// think of it outside the context of the router, if you had pluggable
// portions of your `render`, you might do it like this
<App children={{main: <Users/>, sidebar: <UsersSidebar/>}}/>

// So with the router it looks like this:
const routes = (
  <Route component={App}>
    <Route path="groups" components={{main: Groups, sidebar: GroupsSidebar}}/>
    <Route path="users" components={{main: Users, sidebar: UsersSidebar}}>
      <Route path="users/:userId" component={Profile}/>
    </Route>
  </Route>
)

class App extends React.Component {
  render () {
    const { main, sidebar } = this.props;
    return (
      <div>
        <div className="Main">
          {main}
        </div>
        <div className="Sidebar">
          {sidebar}
        </div>
      </div>
    )
  }
}

class Users extends React.Component {
  render () {
    return (
      <div>
        {/* if at "/users/123" `children` will be <Profile> */}
        {/* UsersSidebar will also get <Profile> as this.props.children,
            so its a little weird, but you can decide which one wants
            to continue with the nesting */}
        {this.props.children}
      </div>
    )
  }
}

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

Edit: Согласно комментарию @Luiz:

В последней версии маршрутизатора (v3) компоненты находятся в корневом объекте реквизита

Итак:

const { main, sidebar } = this.props.children;

становится:

const { main, sidebar } = this.props;

EDIT: В ответном маршрутизаторе v4 это может быть выполнено как (в соответствии с примером, представленным в новых документах):

import React from 'react'
import {
  BrowserRouter as Router,
  Route,
  Link
} from 'react-router-dom'

// Each logical "route" has two components, one for
// the sidebar and one for the main area. We want to
// render both of them in different places when the
// path matches the current URL.
const routes = [
  { path: '/',
    exact: true,
    sidebar: () => <div>home!</div>,
    main: () => <h2>Home</h2>
  },
  { path: '/bubblegum',
    sidebar: () => <div>bubblegum!</div>,
    main: () => <h2>Bubblegum</h2>
  },
  { path: '/shoelaces',
    sidebar: () => <div>shoelaces!</div>,
    main: () => <h2>Shoelaces</h2>
  }
]

const SidebarExample = () => (
  <Router>
    <div style={{ display: 'flex' }}>
      <div style={{
        padding: '10px',
        width: '40%',
        background: '#f0f0f0'
      }}>
        <ul style={{ listStyleType: 'none', padding: 0 }}>
          <li><Link to="/">Home</Link></li>
          <li><Link to="/bubblegum">Bubblegum</Link></li>
          <li><Link to="/shoelaces">Shoelaces</Link></li>
        </ul>

        {routes.map((route, index) => (
          // You can render a <Route> in as many places
          // as you want in your app. It will render along
          // with any other <Route>s that also match the URL.
          // So, a sidebar or breadcrumbs or anything else
          // that requires you to render multiple things
          // in multiple places at the same URL is nothing
          // more than multiple <Route>s.
          <Route
            key={index}
            path={route.path}
            exact={route.exact}
            component={route.sidebar}
          />
        ))}
      </div>

      <div style={{ flex: 1, padding: '10px' }}>
        {routes.map((route, index) => (
          // Render more <Route>s with the same paths as
          // above, but different components this time.
          <Route
            key={index}
            path={route.path}
            exact={route.exact}
            component={route.main}
          />
        ))}
      </div>
    </div>
  </Router>
)

export default SidebarExample

Убедитесь, что вы проверили новые документы React Router v4 здесь: https://reacttraining.com/react-router/

Ответ 2

Компонент может быть функцией, которая возвращает JSX.

  <Route>
    <Route path="/" component={App}>
      <IndexRoute component={Home} />
      <Route path="Invite" component={()=>(<div><Home/><Invite/></div>)} />
    </Route>
  </Route>

Ответ 3

2019 +

Простой и понятный способ сделать это и избежать неправильного повторного рендеринга (протестирован на реагирующем маршрутизаторе v5, необходимо подтвердить на реагирующем маршрутизаторе v4):

       <Switch>
         <Route exact path={["/route1/:id/:token", "/"]}>
          <Layout1>
            <Route path="/route1/:id/:token" component={SetPassword} />
            <Route exact path="/" component={SignIn} />
          </Layout1>
        </Route>
        <Route path={["/route2"]}>
          <Layout2>
            <Route path="/route2" component={Home} />
          </Layout2>
        </Route>
      </Switch>

который можно изменить на:

const routes = [
  {
    layout:Layout1,
    subRoutes:[
      {
        path:"/route1/:id/:token",
        component:SetPassword
      },
      {
        exact:true,
        path:"/",
        component:SignIn
      },
    ]
  },
  {
    layout:Layout2,
    subRoutes:[
      {
        path:"/route2",
        component:Home
      },
    ]
  }
];

с:

      <Switch>
        {routes.map((route,i)=>
          <Route key={i} exact={route.subRoutes.some(r=>r.exact)} path={route.subRoutes.map(r=>r.path)}>
            <route.layout>
              {route.subRoutes.map((subRoute,i)=>
                <Route key={i} {...subRoute} />
              )}
            </route.layout>
          </Route>
        )}
      </Switch>