[译]不配置,不出事?Router Router v4那些坑(其一)

王子腾
• 阅读 4491

原文

文中的一些名词
路径(path):指route上的参数path
路径名(pathname):指location的路径名

React Router 4与前代相比最大的变化莫过于其不再需要配置。相对的,应用服务为自身的"配置",并确定渲染时该呈现的内容。这种新方式通畅运作良好,但还是可能跳坑的。

对比

首先我们来回顾一下先前和现在的版本的工作流程上的区别。

旧版本

之前,我们需要配置一系列路由。你可以自行定义对象来配置,也可以通过<Route>组件来构建。

<Router routes={{ path: '/', component: App, children: [...]}/>
// or
<Router>
  <Route path='/' component={App}>
    ...
  </Route>
</Router>

<Route>看似一个真正的组件,实则为其参数服务。
当你写出如下代码:

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

其实他等价于

React.createElement(
  Route,
  { path: '/', component: App },
  React.createElement(Route, { path: 'about', component: About })
)

React Router只关心从React元素中获得的属性。

{
  path: '/',
  component: App,
  children: [
    { path: 'about', component: About}
  ]
}

一旦location变化,React Router会遍历配置对象,来确定新location匹配的路径。为了执行后续操作(如获取数据,加载异步组件,限制访问时的重定向),将会为路由调用enter/update/exit方法。最终,对于匹配的路径,依据路由的component参数来创建React元素。在当前路径下,所有元素将被组合在一起(通过this.props.children)并渲染出来。

现在的方式

第4代中,<Route>是一个真正的组件。当应用渲染时,路由(route)会将自己的路径(path)与当前location的路径名进行比较。如果匹配上,调用<Route>的render方法返回React元素,如果不匹配,则返回null

<Route path='/here' component={Here} />
// { pathname: "/here" }
return React.createElement(Here, { history, match, location })
// { pathname: "/elsewhere" }
return null

定义子路由时,子路由需要被放置在一个由父路由渲染的组件中([[译注意]怎么都觉得拗口,看代码就清楚了)

const Child = () => <div>Child component</div>
const Parent = () => (
  <div>
    <h2>Parent component</h2>
    <Route path='/parent/child' component={Child}/>
  </div>
)
ReactDOM.render((
  <BrowserRouter>
    <Route path='/parent' component={Parent}/>
  </BrowserRouter>
), holder)

通过使用<Switch>组件,来创建分支点,这些点中只有一个的路由能匹配。这常被用于有多个路径可以匹配中同一个路径名或需要一个'miss'组件对路径全部匹配不上的情况作处理。

即便不需要处理上述的情形,将路由放置于<Switch>组件中也是一个好方法,其既可以保持路由逻辑又可以得到更明晰的DOM结构。

<Switch>
  <Route path='/the-good' component={Good}/>
  <Route path='/the-bad' component={Bad}/>
  <Route path='/the-ugly' component={Ugly}/>
</Switch>

React的生命周期方法可以处理任意的enter/exit/update 调用。componentWillMountcomponentDidMount将处理enter,componentWillUpdate componentDidUpdate将处理update,componentWillUnmount将处理exit。

区别

4代的方式大大简化了应用开发。通过React Router构建应用与常规React构建极其相似。有些内容你希望在特定的location下展示,你可以将其放置于<Route>中。(从无路由的React应用可以轻松改造成支持路由的应用)

然而无集中配置也纯在一些问题。在你在渲染前需要确认被匹配的路由时,你会踩坑的。会出现以下问题:

  1. 全局的404页面

  2. (批量) 数据获取

  3. 带有异步组件的服务端渲染

对于上述问题,一个路由配置可以执行额外的步骤,以保证应用的正确渲染。

当"控制环节"在渲染步骤进行时,就不存在匹配路由与渲染她们的缓存区。这并不意味这些问题都被搞定了,这是变了个花样罢了。

解决方法

在后续的章节,我们会介绍在这些情形下,如何使用React Router v4去分析。他们并不一定给你解决方案,但可以为你指出正确的方向。请记住React Router v4还刚发布不久。在很多方面它确实能做到开箱即用,但它也不是能适应所有场景的"万能"库。
幸运的事,React拥有一个相当活跃的社区,并有很多人使用React Router。虽然需要一些时日,但是随着越来越多的人使用React Router v4,将会有更多不同的解决方案被提出。如果你想出了一个好的解决方案,请把它分享出来。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Stella981 Stella981
3年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
ELK学习笔记之配置logstash消费kafka多个topic并分别生成索引
0x00 filebeat配置多个topicfilebeat.prospectors:input_type:logencoding:GB2312fields_under_root:truefields:添加字段
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Easter79 Easter79
3年前
SpringBoot整合Redis乱码原因及解决方案
问题描述:springboot使用springdataredis存储数据时乱码rediskey/value出现\\xAC\\xED\\x00\\x05t\\x00\\x05问题分析:查看RedisTemplate类!(https://oscimg.oschina.net/oscnet/0a85565fa
Wesley13 Wesley13
3年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(