Переход с реактивного маршрутизатора 3.x на 4.x

Как я могу перейти к использованию https://cdnjs.cloudflare.com/ajax/libs/react-router/4.0.0-2/react-router.min.js с использования https://cdnjs.cloudflare.com/ajax/libs/react-router/3.0.1/ReactRouter.min.js?

Пример использования 3.x ниже.

HTML

<script src="https://unpkg.com/[email protected]/dist/react.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/react-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-router/3.0.1/ReactRouter.min.js"></script>

JS

let { Router, IndexRoute, Redirect, Route, Link, browserHistory } = ReactRouter;

history.replaceState(0,0,'/');

const Main = () =>
  <Router history={browserHistory}>

    <Route path='/' component={App}>
      <IndexRoute component={Home}/>
      <Route path='map' component={Map}/>
      <Route path='settings' component={Settings}/>
            <Redirect from='foo' to='/' />
      <Route path='*' component={NotFound}/>
    </Route>

  </Router>

const App = props => 
  <div>
    <Navigation>
      <Link to='/map'>Map</Link>
      <Link to='/settings'>Settings</Link>
      <Link to='/foo'>Foo</Link>
    </Navigation>

    {props.children}

  </div>

const Navigation = props => <nav {...props} />
const Home = () => <h1>Home</h1>
const Map = () => <h1>Map</h1>
const Settings = () => <h1>Settings</h1>
const NotFound = (props) => <h1>404 - Not Found</h1>

ReactDOM.render(<Main />, document.body);

Посмотрите его в действии по адресу: https://jsfiddle.net/developit/nvpr63eg/.

Если я перейду на любую из версий 4.x, размещенных на CDN, это не сработает (недостижимый код после оператора return).


person rich    schedule 17.01.2017    source источник


Ответы (5)


Я смог настроить его с помощью редукса, изменив несколько вещей:

Во-первых, browserHistory больше не определен в react-router. Один из способов вернуть его — использовать пакет history.

Вам нужно будет установить (редукс опционально):

npm i -S history react-router react-router-redux

Вместо того, чтобы пытаться импортировать browserHistory, используйте:

import { createBrowserHistory } from 'history';

Если вы хотите использовать редукцию, импортируйте это и добавьте в свои комбинированные редукторы:

import { routerReducer as routing } from 'react-router-redux';

combineReducers({
  home, about,
  routing, // new
});

Затем вы создаете объект history

// redux
import { syncHistoryWithStore } from 'react-router-redux';
const history = syncHistoryWithStore(createBrowserHistory(), store);

// regular
const history = createBrowserHistory();

Затем измените свой маршрутизатор, чтобы использовать новый объект history.

<Router history={ history } children={ Routes } />

Все остальное должно быть таким же.


Если кто-то столкнется с The prop history is marked as required in Router, but its value is undefined.

Это связано с тем, что browserHistory больше не доступен в реагирующем маршрутизаторе, см. сообщение, чтобы использовать пакет истории вместо этого.


Связанный

person BrunoLM    schedule 17.03.2017

Это дополнительный ответ на ответ Пола С., опубликованный выше. Кредит все равно должен перейти к Полу за его публикацию.

Причина m, дополняющая ответ, bcoz: -

  1. Я получил ошибки с BrowserHistory и Link.
  2. Мне пришлось включить react-router-dom.
  3. была опечатка (в оригинальном ответе Пауля)

шаги пряжи:

yarn add react-router
yarn add react-router-dom

пакет.json:

 "react": "^15.6.1",
    "react-dom": "^15.6.1",
    "react-router": "^4.1.1",
    "react-router-dom": "^4.1.1"

index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import { Switch, Redirect, Route} from 'react-router';
import {BrowserRouter, Link} from 'react-router-dom';


//let { BrowserRouter, Switch, Redirect, Route, Link } = ReactRouter;

const Main = () =>
  <BrowserRouter>
    <App>
      <Switch>
        <Route exact path='/' component={Home}/>
        <Route path='/map' component={Map}/>
        <Route path='/settings' component={Settings}/>
        <Route path='/foo' component={Foo}/>
        <Route component={NotFound}/>
      </Switch>
    </App>
  </BrowserRouter>

const App = props =>
  <div>
    <Navigation>
      <Link to='/map'>Map</Link>
      <Link to='/settings'>Settings</Link>
      <Link to='/foo'>Foo</Link>
    </Navigation>

    {props.children}

  </div>

const Navigation = props => <nav {...props} />
const Home = () => <h1>Home</h1>
const Map = () => <h1>Map</h1>
const Settings = () => <h1>Settings</h1>
const Foo = () => <Redirect to='/' />
const NotFound = (props) => <h1>404 - Not Found</h1>

ReactDOM.render(<Main />, document.body);

введите описание изображения здесь

person Plankton    schedule 16.06.2017
comment
Это самый полезный ответ; Я собирался опубликовать то же самое, прочитав первые 3 или 4, и ничего не понял. - person Rob Grant; 30.06.2017

Ближе к полной версии должно быть руководство по обновлению. Я адаптировал ваш код для предстоящей бета-версии вместо текущей альфы. Бета-версия еще не выпущена, поэтому, к сожалению, нет размещенной версии React Router, с помощью которой вы сможете это протестировать.

let { BrowserRouter, Switch, Redirect, Route, Link } = ReactRouter;

const Main = () =>
  <BrowserRouter>
    <App>
      <Switch>
        <Route exact path='/' component={Home}/>
        <Route path='/map' component={Map}/>
        <Route path='/settings' component={Settings}/>
        <Route path='/foo' component={Foo}/>
        <Route component={NotFound}/>
      </Switch>
    </App>
  </BrowserRouter>

const App = props => 
  <div>
    <Navigation>
      <Link to='/map'>Map</Link>
      <Link to='/settings'>Settings</Link>
      <Link to='/foo'>Foo</Link>
    </Navigation>

    {props.children}

  </div>

const Navigation = props => <nav {...props} />
const Home = () => <h1>Home</h1>
const Map = () => <h1>Map</h1>
const Settings = () => <h1>Settings</h1>
const Foo = () => <Redirect to='/' />
const NotFound = (props) => <h1>404 - Not Found</h1>

ReactDOM.render(<Main />, document.body);
person Paul S    schedule 17.01.2017
comment
Короткий и сладкий. заставил меня работать в кратчайшие сроки. есть опечатка в закрывающем теге ‹/BrowserRouter›. вы можете исправить это. - person Plankton; 16.06.2017

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

Ознакомьтесь с официальной документацией здесь. Также есть хороший FAQ об этих изменениях, здесь. Вот отрывок:

Почему такое огромное изменение?

tl;dr Декларативная компонуемость.

Мы никогда не были так взволнованы React Router. Как и вы, мы многое узнали о React с тех пор, как начали его использовать. Мы построили маршрутизатор наилучшим образом, как только могли. Что мы узнали больше всего, так это то, что мы любим React из-за его декларативной компонуемости.

Если вы хотите обновиться, согласно официальному источнику, скоро появится руководство по обновлению:

Мы твердо верим в итеративную миграцию, а не в перезапись приложений. Мы работаем над руководством по миграции, но основная стратегия заключается в том, что обе версии будут работать в тандеме (из-за ограничений npm мы опубликуем предыдущую версию отдельно, чтобы можно было установить обе).

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


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

const App = props => 
  <div>
    <Navigation>
      <Link to='/map'>Map</Link>
      <Link to='/settings'>Settings</Link>
      <Link to='/foo'>Foo</Link>
    </Navigation>
    {props.children}
  </div>

  <Match exactly pattern="/" component={Home} />
  <Match pattern="/map" component={Map} />
  <Match pattern="/settings" component={Settings} />
  <Match pattern="/topics" component={Topics} />

Надеюсь это поможет. Удачи.


изменить: видимо, у @PaulS есть пример для будущей версии React-Router v4. Если сообщение верное, приведенный выше код не будет работать в будущем; это будет работать только для текущей доступной версии. Следите за информацией на указанных выше страницах, чтобы узнать, когда RRv4 выйдет в эфир.

person Chris    schedule 17.01.2017
comment
Единственная реальная разница между вашим кодом и моим заключается в том, что <Match> был переименован в <Route>, а реквизит pattern теперь path. Они такие же, как и в v2/3, что облегчит людям обновление их приложений. - person Paul S; 17.01.2017

В недавнем выпуске v4 следует отметить несколько моментов, касающихся вашего jsfiddle. Во-первых, библиотека в целом была разделена: веб, нативная и базовая (используйте где угодно). Используйте react-router-dom только для Интернета.

2: Способ вложения маршрутов совершенно другой. Вместо того, чтобы вкладывать маршруты в ваш родительский компонент, что вы на самом деле не можете сделать, все, что вам нужно сделать, это определить свой родительский компонент (в данном случае BrowserRouter), а затем вы можете свободно определять маршруты для своих компонентов. Теперь ваши компоненты определяют иерархию. Например, вы можете организовать компоненты Main и App следующим образом:

const Main = () => (
  <BrowserRouter>
    <App />
  </BrowserRouter>
)

const App = props => (
  <div>
    <Navigation>
      <Link to='/'>Home</Link>
      <Link to='/map'>Map</Link>
      <Link to='/settings'>Settings</Link>
      <Link to='/foo'>Foo</Link>
    </Navigation>

    <Route exact path='/' component={Home}/>
    <Route path='/map' component={Map}/>
    <Route path='/settings' component={Settings}/>
    <Route path='/foo' render={() => (
        <Redirect to="/"/>
    )}/>
  </div>
)

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

https://jsfiddle.net/bagofcole/kL6m8pjk/12/

Для получения дополнительной информации посетите: https://reacttraining.com/react-router/web/guides/quick-start

person colemerrick    schedule 06.05.2017