续接上文【Webpack4+React16+ReactRouter4整合开发】
拉取github代码
https://github.com/durban89/webpack4-react16-reactrouter-demo.git
1 2 3 4
| git clone https://github.com/durban89/webpack4-react16-reactrouter-demo.git webpack4-react16-reactrouter-redux cd webpack4-react16-reactrouter-redux npm install npm start
|
如果没有异常就可以正常写代码了
首先看下react-router-redux,从react-router官网的redux介绍部分可以看出写的是React Router Redux,但是点击后会告诉你Deprecated。我的天!废弃了,好吧,然后下面告诉你connected-react-router
我的天,又造了一个轮子,看来要重头学起了,没关系,咱们就是不怕折腾,人活着就是折腾嘛。
我们链接到connected-react-router,各种的炫耀夸,太多了,各种优点,我们还是来点实际的,操作开始
1
| npm install redux react-redux history react-hot-loader connected-react-router --save
|
如何使用
修改src/index.jsx
1、第一步
添加第一部分 - 导入使用的库函数
1 2 3 4 5
| import { AppContainer } from 'react-hot-loader'; import { createBrowserHistory } from 'history'; import { applyMiddleware, compose, createStore } from 'redux'; import { Provider } from 'react-redux'; import { connectRouter, ConnectedRouter, routerMiddleware } from 'connected-react-router';
|
添加第二部分 - 需要自己去定义
1 2
| import rootReducer from './reducers'; import routes from './routes';
|
添加第三部分 - 配置redux相关的逻辑
1 2 3 4 5 6 7 8
| const history = createBrowserHistory(); const initialState = {}; const composeEnhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; const store = createStore( connectRouter(history)(rootReducer), initialState, composeEnhancer(applyMiddleware(routerMiddleware(history))), );
|
添加第四部分 - 整合react-router
1 2 3 4 5 6 7 8 9 10 11 12
| ReactDOM.render( ( <AppContainer> <Provider store={store}> <ConnectedRouter history={history}> {routes} </ConnectedRouter> </Provider> </AppContainer> ), document.getElementById('root'), );
|
最终src/index.jsx内容如下
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
| import React from 'react'; import { AppContainer } from 'react-hot-loader'; import { createBrowserHistory } from 'history'; import { applyMiddleware, compose, createStore } from 'redux'; import { Provider } from 'react-redux'; import { connectRouter, ConnectedRouter, routerMiddleware } from 'connected-react-router'; import ReactDOM from 'react-dom'; import rootReducer from './reducers'; import routes from './routes';
const history = createBrowserHistory(); const initialState = {}; const composeEnhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; const store = createStore( connectRouter(history)(rootReducer), initialState, composeEnhancer(applyMiddleware(routerMiddleware(history))), );
ReactDOM.render( ( <AppContainer> <Provider store={store}> <ConnectedRouter history={history}> {routes} </ConnectedRouter> </Provider> </AppContainer> ), document.getElementById('root'), );
|
src/routes.jsx 主要配置路由跟组件的关系 -> 上面这行import routes from ‘./routes’;代码
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
| import React from 'react'; import { BrowserRouter as Router, Route, Link as ALink, } from 'react-router-dom';
import AppComponent from './components/AppComponent'; import HomeComponent from './components/HomeComponent'; import AboutComponent from './components/AboutComponent'; import TopicsComponent from './components/TopicsComponent';
const routes = ( <div> <Router> <AppComponent> <ul> <li><ALink to="/">首页</ALink></li> <li><ALink to="/about">关于</ALink></li> <li><ALink to="/topics">论题</ALink></li> </ul> <hr />
<Route exact path="/" component={HomeComponent} /> <Route path="/about" component={AboutComponent} /> <Route path="/topics" component={TopicsComponent} /> </AppComponent> </Router> </div> );
export default routes;
|
2、第二步
配置好了,就要开始使用了
1】、创建reducers
src/reducers/counter.js
1 2 3 4 5 6 7 8 9 10 11 12
| const counterReducer = (state = 0, action) => { switch (action.type) { case 'INCREMENT': return state + 1; case 'DECREMENT': return state - 1; default: return state; } };
export default counterReducer;
|
2】、将counter.js加入到主reducers里面
1 2 3 4 5 6 7
| src/reducers/index.js import { combineReducers } from 'redux'; import counterReducer from './counter';
export default combineReducers({ count: counterReducer, });
|
3】、创建actions
src/actions/counter.js1 2 3 4 5 6 7 8
| export const increment = () => ({ type: 'INCREMENT', });
export const decrement = () => ({ type: 'DECREMENT', });
|
4】、添加一个组件src/components/CounterComponent.jsx
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
| import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { counter } from 'Actions';
const { increment, decrement, } = counter;
class CounterComponent extends Component { constructor(props, context) { super(props, context);
this.state = {}; }
render() { const { count, } = this.props;
return ( <div> <p>数值: {count}</p> <button onClick={this.props.doIncrement}>+</button> <button onClick={this.props.doDecrement}>-</button> </div> ); } }
CounterComponent.propTypes = { count: PropTypes.number, doIncrement: PropTypes.func.isRequired, doDecrement: PropTypes.func.isRequired, };
CounterComponent.defaultProps = { count: 0, };
const mapStateToProps = state => ({ count: state.count, });
const mapDispatchToProps = dispatch => ({ doIncrement: () => dispatch(increment()), doDecrement: () => dispatch(decrement()), });
export default connect(mapStateToProps, mapDispatchToProps)(CounterComponent);
|
5】、将组件加到路由里面
src/routes.js
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
| import React from 'react'; import { BrowserRouter as Router, Route, Link as ALink, } from 'react-router-dom';
import AppComponent from './components/AppComponent'; import HomeComponent from './components/HomeComponent'; import AboutComponent from './components/AboutComponent'; import TopicsComponent from './components/TopicsComponent'; import CounterComponent from './components/CounterComponent';
const routes = ( <div> <Router> <AppComponent> <ul> <li><ALink to="/">首页</ALink></li> <li><ALink to="/about">关于</ALink></li> <li><ALink to="/topics">论题</ALink></li> <li><ALink to="/counter">计数器</ALink></li> </ul> <hr />
<Route exact path="/" component={HomeComponent} /> <Route path="/about" component={AboutComponent} /> <Route path="/topics" component={TopicsComponent} /> <Route path="/counter" component={CounterComponent} /> </AppComponent> </Router> </div> );
export default routes;
|
6】、为了引入方便再加一个src/actions/index.js
1 2 3 4 5 6 7 8
| import counter from './counter';
const actions = { counter, };
export default actions; export { counter };
|
到这里基本上就完工了,应该可以在页面看到计数器,并进行操作了
1
| import { counter } from 'Actions';
|
这里是比较特殊的
这个要归功于webpack
1 2 3 4 5 6
| resolve: { extensions: ['.js', '.jsx'], alias: { Actions: path.resolve(__dirname, 'src/actions'), }, },
|
这里我们加了这个配置,于是在引入的时候就会正常引入需要的代码了。
好了,整个配置就完成了,项目我已经上传到github了,需要的同学可以自行去下载查看
实例项目地址:
https://github.com/durban89/webpack4-react16-reactrouter-demo.git
tag: v_1.0.1