connected-react-router
1.项目依赖
npm install redux react-redux react-router-dom connected-react-router -S
2.使用

2.1.src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { Route, Link } from 'react-router-dom';
import { ConnectedRouter } from 'connected-react-router';
import history from './history';
import store from './store';
import Home from './components/Home';
import Counter from './components/Counter';
ReactDOM.render(<Provider store={store}>
<ConnectedRouter history={history}>
<>
<Link to='/' >Home</Link> |
<Link to='/counter'>Counter</Link>
<Route path='/' exact component={Home} />
<Route path='/counter' exact component={Counter} />
</>
</ConnectedRouter>
</Provider>, document.getElementById('root'));
2.2.components/Home.js
import React from 'react';
class Home extends React.Component {
render() {
return <div>
<h1>Home</h1>
<button onClick={() => this.props.history.go(-1)}>返回</button>
</div>
}
}
export default Home;
2.3.components/Counter.js
import React from 'react';
import { connect } from 'react-redux';
import actions from '../store/actions/counter';
class Counter extends React.Component {
render() {
return <div>
<p>{this.props.num}</p>
<button onClick={this.props.add}>+</button>
<button onClick={this.props.minus}>-</button>
<button onClick={() => this.props.go('/')}>go home</button>
</div>
}
}
const mapStateToProps = state => state.counter;
export default connect(mapStateToProps, actions)(Counter);
2.4.src/history.js
import {createBrowserHistory} from 'history';
export default createBrowserHistory();
2.5.store/index.js
import { applyMiddleware, createStore } from 'redux';
import { routerMiddleware } from 'connected-react-router';
import history from '../history';
import reducers from './reducers';
export default applyMiddleware(routerMiddleware(history))(createStore)(reducers);
2.6.store/action-types.js
const ADD = 'ADD';
const MINUS = 'MINUS';
export {
ADD,
MINUS
}
2.7.store/actions/counter.js
import { push } from 'connected-react-router';
import * as types from '../action-types';
const actions = {
add() {
return { type: types.ADD };
},
mimus() {
return { types: types.MINUS };
},
go(path) {
return push(path);
}
}
export default actions
2.8.store/reducers/index.js
import { combineReducers } from 'redux';
import { connectRouter } from 'connected-react-router';
import counter from './counter';
import history from '../../history';
const reducers = {
router: connectRouter(history),
counter
}
export default combineReducers(reducers);
2.9.store/reducers/counter.js
import * as types from '../action-types';
const initialState = { num: 0 };
function reduer(state = initialState, action) {
switch (action.type) {
case types.ADD:
return { num: state.num + 1 }
case types.MINUS:
return { num: state.num - 1 }
default:
return state
}
}
export default reduer;
3.实现
connected-react-router
├── ConnectedRouter.js
├── action-types.js
├── actions.js
├── connectRouter.js
├── index.js
└── routerMiddleware.js
3.1.index.js
export {default as ConnectedRouter} from './ConnectedRouter';
export {default as connectRouter} from './connectRouter';
export {default as routerMiddleware} from './routerMiddleware';
3.2.ConnectedRouter.js
import React from 'react';
import { connect } from 'react-redux';
import { Router } from 'react-router';
import { locationChange } from './actions'
class ConnectedRouter extends React.Component {
componentDidMount() {
const { history, dispatch } = this.props
history.listen((location, action) => {
const newAction = locationChange(location, action);
dispatch(newAction);
})
}
render() {
const { history, children } = this.props
return <Router history={history}>
{children}
</Router>
}
}
export default connect()(ConnectedRouter);
3.3.action-types.js
export const CALL_HISTORY_METHOD = '@@router/CALL_HISTORY_METHOD';
export const LOCATION_CHANGE = '@@router/LOCATION_CHANGE';
3.4.actions.js
import * as types from './action-types';
export function locationChange(location, action) {
return {
type: types.LOCATION_CHANGE,
payload: {
location,
action
}
}
}
export function push(path) {
return {
type: types.CALL_HISTORY_METHOD,
payload: {
method: 'push',
args: [path]
}
}
}
3.5.routerMiddleware.js
import * as types from './action-types'
function routerMiddleware(history) {
return middlewareApi => next => action => {
if (action.type !== types.CALL_HISTORY_METHOD) {
return next(action);
}
const { payload: { method, args } } = action;
history[method](...args);
}
}
export default routerMiddleware;
3.6.connectRouter.js
import * as types from './action-types'
function connectRouter(history) {
const initialState = {
location: history.location,
action: history.action
}
return (state = initialState, action) => {
switch (action.type) {
case types.LOCATION_CHANGE:
return { ...state, ...action.payload }
default:
return state;
}
}
}
export default connectRouter;