爱凉拌菜真是太好了

react-router V4 踩坑

The prop `history` is marked as required in `Router` …

The prop `history` is marked as required in `Router`, but its value is `undefined`. in Router

解决办法:

出现这个报错是因为我用npm 安装的是react-router v4,react-router v4不再使用<Router history={hashHistory}> 这种方式定义history 实现类型。而是直接通过组件如BrowserRouter,HashRouter等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import {Router, Route, hashHistory} from 'react-router';
<Router history={hashHistory}>
<Route path="/" component={Main}></Route>
</Router>
===>
import {BrowserRouter as Router, Route} from 'react-router-dom';
<Router>
<Route path="/" component={Main}></Route>
</Router>
或者
<HashRouter>
<Route path="/" component={Main}></Route>
</HashRouter>

A ‘Router’ may have only one child element

react-router v4 在 下面只能放一个层级,类似与react 中render 不能有两个平级div一样

解决办法:

用div 或者Switch 包裹所有Route

1
2
3
4
5
6
7
8
<Router>
<div>
<Route component={ComponentHeader}></Route>
<Switch>
<Route component={ComponentFooter} path='/footer/:id'></Route>
</Switch>
</div>
</Router>

webpack 配置问题

v4 中引入<BrowserRouter> 组件, 而BrowserRouter使用的是HTML5 的history api, 在使用webpack-dev-server时会遇到

GET http://localhost:8080/xxx/xxx 404 (Not Found)

解决办法:

webpack.config.js中加入

1
2
3
4
5
6
7
devServer: {
apiHistoryFallback: true,
}
output: {
...,
publicPath: '/',
}

然后将index.html中的bundle.js改为/bundle.js

1
<script src='bundle.js'></script> ===> <script src='/bundle.js'></script>

参考:https://stackoverflow.com/questions/43209666/react-router-v4-cannot-get-url

question

https://segmentfault.com/q/1010000010432084?_ea=2287891

静态路由和动态路由

https://reacttraining.com/react-router/web/guides/philosophy

react-router 传参

使用/xxx/:someparam 的形式书写Route 的path属性,如:

1
<Route component={ComponentFooter} path='/footer/:id'></Route>

然后Link 的to属相加上参数即可,如:

1
<Link to='/footer/1234'>Ant design demo 1</Link>

最后在ComponentFooter中通过this.props.match.params访问,如:

1
2
3
<footer className={footerCss.miniFooter}>
<em>id:{this.props.match.params.id}</em>
</footer>

完整代码

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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/**
* js|
* |root.js
*/
import React from 'react';
import ReactDOM from 'react-dom';
import ComponentHeader from './components/header';
// import ComponentFooter from './components/footer';
var footerCss = require('../css/footer.css');
import {BrowserRouter as Router, Route, Switch, Link} from 'react-router-dom';
class App extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<Router>
<div>
<Route component={ComponentHeader}></Route>
<Switch>
<Route component={ComponentFooter} path='/footer/:id'></Route>
</Switch>
</div>
</Router>
)
}
}
class ComponentFooter extends React.Component {
constructor() {
super();
}
render() {
return (
<footer className={footerCss.miniFooter}>
<em>id:{this.props.match.params.id}</em>
<h1><Link to={`${this.props.match.url}/cr`}>footer</Link></h1>
<Route component={CopyRight} path={`${this.props.match.url}/cr`}></Route>
</footer>
)
}
}
class CopyRight extends React.Component {
constructor() {
super();
}
render() {
return (
<a>copyright</a>
)
}
}
ReactDOM.render(
<App />,document.getElementById('root')
)
/**
* js|
* |components|
* |header.js
*/
import React from 'react';
import {Link} from 'react-router-dom';
var headerCss = require('../../css/header.css');
export default class Header extends React.Component {
constructor() {
super();
}
render() {
console.log(headerCss);
return (
<header className={headerCss.bgheader}>
<h1><Link to='/footer/1234'>Ant design demo 1</Link></h1>
</header>
)
}
}