从react-router 3.x 移动到 4.x

IT技术 javascript reactjs react-router react-router-v4
2021-04-19 18:29:56

如何https://cdnjs.cloudflare.com/ajax/libs/react-router/4.0.0-2/react-router.min.js从 using转到using https://cdnjs.cloudflare.com/ajax/libs/react-router/3.0.1/ReactRouter.min.js

下面使用 3.x 的示例。

HTML

<script src="https://unpkg.com/react@15.4.2/dist/react.min.js"></script>
<script src="https://unpkg.com/react-dom@15.4.2/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/

如果我移动到任何 CDN 托管的 4.x 版本,尽管它不起作用(返回语句后无法访问代码)。

5个回答

我可以通过更改一些东西来使用 redux 配置它:

首先,browserHistory不再定义react-router取回它的一种方法是使用 package history

您将需要安装(redux 可选):

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

而不是尝试导入browserHistory使用:

import { createBrowserHistory } from 'history';

如果您想使用 redux,请导入它并将其添加到您的组合减速器中:

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在 react-router 中不再可用,请参阅帖子以使用历史包。


有关的

这是对上面发布的 Paul S 的补充答案。信用仍然应该转到保罗发布它。

补充答案的原因是 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"

索引.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);

在此处输入图片说明

这是最有用的答案;在阅读了前 3 或 4 名后,我正要发布相同的内容,但一无所获。
2021-06-04 18:29:56

应该有一个更接近完整版本的升级指南。我为即将到来的测试版而不是当前的 Alpha 版修改了您的代码。测试版还没有发布,所以很遗憾没有托管版本的 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);
短n甜。让我立即工作。</BrowserRouter> 结束标记有错别字。你可能想要更正。
2021-05-30 18:29:56

您当然可以,但是您需要重写一些组件和应用程序逻辑,因为您的代码不会像当前那样运行。

阅读官方文档,这里还有一个关于这些变化的很好的常见问题解答,这里这是摘录:

为什么会发生巨大的变化?

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 上线时,请留意上面的链接页面以获取信息。

您的代码和我的代码之间唯一真正的区别是<Match>已重命名为<Route>并且pattern道具现在是path. 这些与 v2/3 中的相同,这将使人们更容易升级他们的应用程序。
2021-06-12 18:29:56

关于您的 jsfiddle,最近发布的 v4 有几件事情需要注意。首先,库作为一个整体已经分离:web、native 和 core(在任何地方使用)。仅对 web 使用 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