# React路由组件按需异步加载实践
版本信息:当前使用
React
版本16.13.1
。
# 一、路由的配置
一般来说,我们在React
中写路由的时候都是这样:👇
// 多余代码省略...
import MainPage from "./pages/mainPage";
...
<Switch>
...
<Route strict exact path="/mianpage" component={MainPage} />
...
</Switch>
...
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
但实际上这种写法只适合简单且没几个页面的场景。对于大型项目或者一款产品,路由写死/固定肯定不行(这样维护比较麻烦),它们的路由肯定是动态的、可配置的。
# 二、尝试配置动态路由
# 1.使用() => import(componentPath)
用过Vue
的同学都知道,在Vue-Router
中可以使用component: () => import("./pages/mainPage")
来给路由添加组件。那么React
中也是这样❓
// 多余代码省略...
<Switch>
...
<Route
strict
exact
path="/mianpage"
component={() => import("./pages/mainPage")}
/>
...
</Switch>
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 2.结果报了一堆错误,尝试失败
Uncaught Error: Objects are not valid as a React child (found: [object Promise])...
错误翻译过来就是返回的是
promise
对象。。
# 三、使用中间件异步加载组件
前一节中的错误是因为使用import
返回的是一个promise
对象,显然不能作为组件使用。
此时需要一个中间件对其进行处理并返回一个组件。
展开查看代码
// AsyncComponent.jsx
import React from "react";
// 将普通组件转换为动态组件
const AsyncComponent = (loadComponent, _props) => {
return class extends React.Component {
constructor(props) {
super(props);
this.state = {
Component: null
};
}
componentDidMount() {
if (this.state.Component !== null) return;
loadComponent()
.then(module => module.default)
.then((component) => {
this.setState({Component: component});
})
.catch((err) => {
throw err;
});
}
render() {
const { Component } = this.state;
return (Component) ? <Component {...this.props} {..._props} /> : null;
}
};
};
export default AsyncComponent;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 使用示例
// router 多余代码省略...
import { AsyncComponent } from "./utils/AsyncComponent";
<Switch>
...
<Route
strict
exact
path="/mianpage"
component={AsyncComponent(() => import("./pages/mainPage"), {somePropsData})}
/>
...
</Switch>
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13