react-router 从v2/v3迁移到v4(译文)

react-router 从v2/v3迁移到v4(译文)

原文地址

React Router v4 是完全重写的,所以并没有简单的建议迁移方式。这篇指南提供了一些步骤,从而帮助您了解如何升级您的系统。

注意: 这篇指南同时适用于React Router v2和v3,但是简单起见,示例中仅引用v3

react-router-redux的用户请注意: 并不是所有的包都兼容React Router v4,或者说不能完美兼容。具体的,Redux DevTools的time travel暂时还不可用.

The Router

在React Router v3中, 只有一个<Router>组件。需要为它提供一个history对象作为它的属性.

此外,你有两种方式配置路由表——使用属性routes或者是直接写成<Router>children

// v3
import routes from './routes'
<Router history={browserHistory} routes={routes} />
// or
<Router history={browserHistory}>
  <Route path='/' component={App}>
    // ...
  </Route>
</Router>

而在React Router v4中,一个巨大的变化就是,现在有多个不同作用的路由组件。它们中的任何一个都会为你创建一个history对象。<BrowserRouter>创建browser history,<HashRouter>创建hash history,<MemoryRouter>创建memory history.

在v4中,不再有路由中心配置。当页面需要根据不同路由渲染不同内容的时候,只需要渲染一个<Route>组件。

//v4
<BrowserRouter>
  <div>
    <Route path='/about' component={About} />
    <Route path='/contact' component={Contact} />
  </div>
</BrowserRouter>

有一点需要注意的是,路由组件只能有一个子元素。

// yes
<BrowserRouter>
  <div>
    <Route path='/about' component={About} />
    <Route path='/contact' component={Contact} />
  </div>
</BrowserRouter>

// no
<BrowserRouter>
  <Route path='/about' component={About} />
  <Route path='/contact' component={Contact} />
</BrowserRouter>

Routes

在v3中,<Route>并不是组件。系统中的所有<Route>元素只是用于创建路由配置对象。

/// in v3 the element
<Route path='contact' component={Contact} />
// was equivalent to
{
  path: 'contact',
  component: Contact
}

在v4中,你可以像布局常规React应用一样,去布局应用中的组件。在任何地方,当需要根据不同地址(pathname)来呈现不同内容的时候,你只需要渲染一个<Route>

v4的<Route>是真正的组件,所以无论你在哪里渲染了<Route>,它都会被渲染——当<Route>path与当前地址相匹配时,就会根据赋予给它的属性(componentrenderchildren)渲染内容;而当<Route>path与当前地址不匹配时,则会渲染为null

Nesting Routes

在v3中,嵌套的路由需要被设置成上层<Route>children

<Route path='parent' component={Parent}>
  <Route path='child' component={Child} />
  <Route path='other' component={Other} />
</Route>

当嵌套的路由匹配时,React元素的创建需要同时取决于父子两个<Route>component属性。子元素会作为children属性传递给父元素。

<Parent {...routeProps}>
  <Child {...routeProps} />
</Parent>

在使用v4后,子路由的渲染应该仅由它的上层<Route>组件决定。

<Route path='parent' component={Parent} />

const Parent = () => (
  <div>
    <Route path='child' component={Child} />
    <Route path='other' component={Other} />
  </div>
)

on* properties

React Router v3提供了onEnteronUpdateonLeave方法。这些方法本质上是重写(recreating)了React的生命周期方法。

在v4中,你应该使用<Route>渲染的组件的生命周期方法.
- onEnter:componentDidMount、componentWillMount
- onUpdate:componentDidUpdate、componentWillUpdate(componentWillReceiveProps).
- onLeave:componentWillUnmount

<Switch>

在v3中,你可以指定若干个子路由,而只渲染第一个匹配到的。

// v3
<Route path='/' component={App}>
  <IndexRoute component={Home} />
  <Route path='about' component={About} />
  <Route path='contact' component={Contact} />
</Route>

在v4中的<Switch>组件提供了类似的功能,当<Switch>被渲染时,只有第一个匹配了当前地址的子<Route>才会被渲染。

// v4
const App = () => (
  <Switch>
    <Route exact path='/' component={Home} />
    <Route path='/about' component={About} />
    <Route path='/contact' component={Contact} />
  </Switch>
)

<Redirect>

在v3中,加入你需要从一个路径重定向到另一个路径,例如从“/”到“/welcome”,你需要使用<IndexRedirect >

// v3
<Route path="/" component={App}>
  <IndexRedirect to="/welcome" />
</Route>

在v4中,你可以使用<Redirect>来达到同样的目的。

// v4
<Route exact path="/" render={() => <Redirect to="/welcome" component={App} />} />

<Switch>
  <Route exact path="/" component={App} />
  <Route path="/login" component={Login} />
  <Redirect path="*" to="/" />
</Switch>

v3中,<Redirect>会保留query string:

// v3

<Redirect from="/" to="/welcome" />
// /?source=google → /welcome?source=google

而在v4中,你必须将这些属性显示地重新设置一遍给to

// v4

<Redirect from="/" to="/welcome" />
// /?source=google → /welcome

<Redirect from="/" to={{ ...location, pathname: "/welcome" }} />
// /?source=google → /welcome?source=google

PatternUtils

matchPattern(pattern, pathname)

在v3中,你可以使用内部的用于判断是否相同的代码来检查路径是否匹配。在v4中,可以使用matchPath来完成检查工作,matchPath基于path-to-regexp这个库。

formatPattern(pattern, params)

在v3中,你需要使用PatternUtils.formatPattern通过一个路径模式(一个常量或者是路由中心中的一个配置)和一个包含了若干参数的对象来生成一个有效路径。

// v3
const THING_PATH = '/thing/:id';

<Link to={PatternUtils.formatPattern(THING_PATH, {id: 1})}>A thing</Link>

在v4中,你可以使用path-to-regexp中的compile函数来获得相同的功能。

// v4
const THING_PATH = '/thing/:id';

const thingPath = pathToRegexp.compile(THING_PATH);

<Link to={thingPath({id: 1})}>A thing</Link>

必须设置to属性

在v3中,你可以忽略掉to属性,或者是将它设置为null,用以创建一个没有href属性的锚点

// v3
<Link to={disabled ? null : `/item/${id}`} className="item">
  // item content
</Link>

在v4中,则必须为to赋值,如果确实有需要置空to,可以像下边这样做个简单的封装。

// v4
import { Link } from 'react-router-dom'

const LinkWrapper = (props) => {
  const Component = props.to ? Link : 'a'
  return (
    <Component {...props}>
      { props.children }
    </Component>
  )
}

<LinkWrapper to={disabled ? null : `/item/${id}`} className="item">
  // item content
</LinkWrapper>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值