withRouter作为一个非常常用的组件, 重要性不言而喻, 而它的底层原理你知道吗? 今天来看一下!

一、更新


[2019-4-21]

Changed

  • 改进文章排版格式

二、前言


看完流浪地球, 睡一觉起来继续更新…

不知不觉react-router-dom源码分析系列已经写了9篇, 历经15天寒假, 虽然耗了点实践, 但是总体还是挺值得的.

通过RouterRoute的源码学习, 掌握了history流向react-router-dom顶层, 通过history.listen监听浏览器location变化, 触发setState更新机制, 更新RouterContext. Route接收到最新的context, 结合path-to-regexp库计算出match. 同时也掌握了通过Link组件的自定义链接跳转机制, url变化, 从而触发listen钩子, 调度一系列更新.

今天要学习的withRouter, 同样非常常用, 它可以帮助我们获取到最新的路由信息, 当然也可以执行更新路由等操作.

三、细说


hoist-non-react-statics

正式开始之前, 先来盘一下hoist-non-react-statics这个库.

进入官网, 看到官方的一段英文解释如下:

官方解释

可以了解到, 该库的作用是解决HOC无法传递静态方法的问题. 好吧, 以前从没遇到这个问题, 也许是见识短的缘故吧, 今天先简单了解一下这个库, 知道它怎么用, 后续再深入探究其底层原理.

withRouter

接着看withRouter的总体结构:

1
2
3
4
5
6
7
import hoistStatics from "hoist-non-react-statics";

function withRouter(Component) {
...

return hoistStatics(C, Component);
}

withRouter就是一个HOC组件, 接收一个源component, 返回增强后的component. 顺藤摸瓜, 看到对应的C组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const C = props => {
const { wrappedComponentRef, ...remainingProps } = props;

return (
<Route
children={routeComponentProps => (
<Component
{...remainingProps}
{...routeComponentProps}
ref={wrappedComponentRef}
>
)}
>
);
};

可以看到, C是内部定义的一个enhancedComponent, 也就是增强型组件, 该组件通过返回一个由Route包装过的Element, 将locationmatchhistorycontext作为props传递给wrappedComponent.

好像就是这么点啊? 没错, 就是这么简单, withRouter就是做了这么一件事情, 并不复杂.

四、源码


源码在这里

五、总结


最后, 照例画一张withRouter的思维脑图, 毕竟一图胜千言.

总结