Преимущества динамической и статической маршрутизации в реактиве

Я читаю о статической и динамической маршрутизации в React Router, и я изо всех сил пытаюсь определить преимущества последнего (и почему v4 решил пойти с ним). Я вижу преимущество перечисления всех маршрутов для приложения (статического), а также компонента, к которому привязан каждый маршрут, что позволяет отслеживать, что будет отображаться с учетом определенного URL-адреса. Но я не вижу явного преимущества для динамических маршрутов.

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

В каких ситуациях динамический адрес маршрутизации? Почему предпочтительнее статическая маршрутизация (возможно, в приложениях React)?

Ответ 1

Динамическая маршрутизация

Из документов реагирующих маршрутизаторов:

Когда мы говорим о динамической маршрутизации, мы подразумеваем маршрутизацию, которая имеет место, поскольку ваше приложение выполняет рендеринг, а не в конфигурации или соглашении вне работающего приложения.

Подумайте о маршрутах в качестве компонентов

Ранние версии react-router (pre v4) использовались для статических маршрутов. Это привело к централизованной маршрутизации в приложениях, таких как:

<Router>
    <Route path='/' component={Main}>
      <IndexRoute component={Home} />
      <Route path='about' component={About} />
      <Route onEnter={verifyUser} path='profile' component={Profile} />
      ...
    </Route>
</Router>

Тем не менее, это не совсем так, как Реакт. Реакция фокусируется на композиции с использованием логики компонентов. Таким образом, вместо того, чтобы воображать наши Маршруты как статическую систему, мы можем представить их как компоненты, к которым прибегает реакция-router v4 и основная философия.

Поэтому мы можем использовать Route поскольку мы будем использовать любой компонент React. Это позволяет нам добавлять компоненты Route качестве и когда мы создаем разные компоненты. Одно из преимуществ этого заключается в том, что мы можем отделить логику маршрутизации с компонентами, которые им нужны.

Маршруты вложения

Компонент About может обрабатывать все маршруты и условно отображать части пользовательского интерфейса на основе URL-адреса (например, /about/job или /about/life т.д.).

Другое дело, что компонент Route будет либо отображать компонент для соответствующего маршрута, либо null. Например, следующий Route отображает компонент About для маршрута /about и null (или ничего) в противном случае.

<Route path='about' component={About} />

Это также похоже на то, как мы привыкли условно отображать компоненты в React:

route === '/about' ? <About /> : null

Теперь, если нам нужно отобразить некоторые другие компоненты внутри компонента About для маршрутов /about/job или /about/life мы можем сделать это так:

const About = ({ match ) => (
    <div>
        ...
        <Route path={'${match.url}/job'} component={Job} />
        <Route path={'${match.url}/life'} component={Life} />
    </div>
)

Динамический импорт и разделение кода

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

import Loadable from 'react-loadable';

const Loading = () => (
    <div />
);

const Job = Loadable({
    loader: () => import('./Job'),
    loading: Loading,
});

const Life = Loadable({
    loader: () => import('./Life'),
    loading: Loading,
});

...

render() {
    return (
        ...
        <Route path={'${match.url}/job'} component={Job} />
        <Route path={'${match.url}/life'} component={Life} />
    )
}

Адаптивные маршруты

Другим замечательным вариантом для динамической маршрутизации является создание гибких маршрутов, которые прекрасно объясняются в документах реагирующих маршрутизаторов и рекомендуемом чтении. Вот пример из документов:

const App = () => (
  <AppLayout>
    <Route path="/invoices" component={Invoices}/>
  </AppLayout>
)

const Invoices = () => (
  <Layout>

    {/* always show the nav */}
    <InvoicesNav/>

    <Media query={PRETTY_SMALL}>
      {screenIsSmall => screenIsSmall
        // small screen has no redirect
        ? <Switch>
            <Route exact path="/invoices/dashboard" component={Dashboard}/>
            <Route path="/invoices/:id" component={Invoice}/>
          </Switch>
        // large screen does!
        : <Switch>
            <Route exact path="/invoices/dashboard" component={Dashboard}/>
            <Route path="/invoices/:id" component={Invoice}/>
            <Redirect from="/invoices" to="/invoices/dashboard"/>
          </Switch>
      }
    </Media>
  </Layout>
)

Суммируя документы, вы заметите, насколько простым и декларативным становится добавление Redirect на большие размеры экрана с использованием динамической маршрутизации. Использование статической маршрутизации в таких случаях было бы довольно громоздким и потребовало бы, чтобы мы поместили все маршруты в одном месте. Динамическая маршрутизация упрощает эту проблему, так как теперь логика становится составной (например, компоненты).

статическая маршрутизация

Есть некоторые проблемы, которые не решаются легко с динамической маршрутизацией. Преимущество статической маршрутизации заключается в том, что она позволяет проверять и сопоставлять маршруты перед рендерингом. Следовательно, это полезно, особенно на стороне сервера. Команда реагирующего маршрутизатора также работает над решением, называемым response-router-config, из которого:

С введением React Router v4 больше нет централизованной конфигурации маршрута. Существуют некоторые варианты использования, в которых полезно знать обо всех потенциальных маршрутах приложения, таких как:

  1. Загрузка данных на сервере или в жизненном цикле перед отображением следующего экрана
  2. Связь с маршрутами по названию
  3. Статический анализ

Надеюсь, это дает хорошее резюме как динамической маршрутизации, так и статической маршрутизации и вариантов использования для них :)

Ответ 2

Согласно документам React-Router:

Когда мы говорим о динамической маршрутизации, мы подразумеваем маршрутизацию, которая имеет место, поскольку ваше приложение выполняет рендеринг, а не в конфигурации или соглашении вне работающего приложения. Это означает, что почти все является компонентом в React Router.

Это понятно для объяснения того, что все маршруты, которые вы не инициализировали в начале вашего приложения,

В React-router v3 или ниже он использовал статические маршруты, и все маршруты были инициализированы на верхнем уровне, а вложенность была достигнута как

<Router>
    <Route path='/' component={App}>
      <IndexRoute component={Dashboard} />
      <Route path='users' component={Users}>
          <IndexRoute component={Home}/>
          <Route path="users/:id" component={User}/> 
      </Route>
    </Route>
</Router>

С помощью этой настройки API реактор-маршрутизатор переопределял части React (lifecycles и т.д.), И он просто не соответствовал логике композиции, которую рекомендует React при использовании.

С динамическими маршрутами прогнозируются следующие преимущества:

Вложенные маршруты

Вложенные маршруты с динамической маршрутизацией больше похожи

const App = () => (
    <BrowserRouter>
        {/* here a div */}
        <div>
        {/* here a Route */}
        <Route path="/todos" component={Todos}/>
        </div>
    </BrowserRouter>
)

// when the url matches '/todos' this component renders
const Todos  = ({ match }) => (
    // here a nested div
    <div>
        {/* here a nested Route,
            match.url helps us make a relative path */}
        <Route
        path={'${match.path}/:id'}
        component={Todo}
        />
    </div>
)

В приведенном выше примере, только когда /todos соответствует пути маршрута, компонент Todo монтируется, и только тогда определяется маршрут маршрута /todos/:id.

Адаптивные маршруты

Для этого нужны документы React-router.

Рассмотрим, как пользователь переходит к /invoices. Ваше приложение адаптируется к разным размерам экрана, у них узкий видовой экран, поэтому вы показываете только список счетов и ссылку на dashboard счетов-фактур. Они могут перемещаться глубже оттуда.

Однако на большом экране навигационная панель находится слева, а панель инструментов или отдельные счета-фактуры отображаются справа.

и, следовательно, /invoices не является допустимым Маршрутом для большого экрана, и мы хотели бы перенаправить на /invoices/dashboard. Это может случиться, пользователь поворачивает свой телефон из portait to a landscape mode. Это можно легко выполнить с помощью динамической маршрутизации

const Invoices = () => (
  <Layout>

    {/* always show the nav */}
    <InvoicesNav/>

    <Media query={PRETTY_SMALL}>
      {screenIsSmall => screenIsSmall
        // small screen has no redirect
        ? <Switch>
            <Route exact path="/invoices/dashboard" component={Dashboard}/>
            <Route path="/invoices/:id" component={Invoice}/>
          </Switch>
        // large screen does!
        : <Switch>
            <Route exact path="/invoices/dashboard" component={Dashboard}/>
            <Route path="/invoices/:id" component={Invoice}/>
            <Redirect from="/invoices" to="/invoices/dashboard"/>
          </Switch>
      }
    </Media>
  </Layout>
)

Используя динамические маршруты с React Routers, подумайте о components, а не о статических маршрутах.

Разделение кода

Одна из замечательных особенностей Интернета заключается в том, что нам не нужно заставлять наших посетителей загружать все приложение, прежде чем они смогут его использовать. Вы можете думать о разложении кода как поэтапную загрузку приложения. This is made possible with Dynamic Routing.

Преимущества, которые он приносит, - это то, что весь ваш код не нужно загружать сразу, и, следовательно, он ускоряет первоначальный рендеринг.

Вот хорошая статья, которая поможет вам установитьUp codeSplitting для вашего приложения

Написание композитных аутентифицированных маршрутов

С помощью Dynamic Routing также упростилось писать PrivateRoutes (HOC, который выполняет аутентификацию), что позволяет аутентифицировать пользователей и предоставлять им доступ к определенным маршрутам и перенаправление в противном случае. Этот призыв ко мне все сделал очень общий

Типичный частный маршрут будет выглядеть

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route
    {...rest}
    render={props =>
      fakeAuth.isAuthenticated ? (
        <Component {...props} />
      ) : (
        <Redirect
          to={{
            pathname: "/login",
            state: { from: props.location }
          }}
        />
      )
    }
  />
);

и может использоваться как

<PrivateRoute path="/protected" component={Protected} />