connected-react-router
这个库帮咱们实现了在 redux
中操作路由办法,并将路由变动的信息同步在 redux
的 store
中。
实现流程
actions
封装push
、replace
、go
等次要办法middleware
拦挡actions
信息,触发封装好的action
办法reducer
新增router
的state信息ConnectedRouter
组件监听路由变动,更新路由信息到store
依赖库和目录构造
依赖库
- history
- react-router
目录构造
- index.js // 入口文件
- constant.js // actions 常量
- push.js // 这里只封装history中的push办法,其它大同小异了
- connectRouter.js // reducer 中同步路由变动的信息
- routerMiddleware.js // 中间件,拦挡 action 触发路由更新
- ConnectedRouter.js // 组件,主要用途是监听路由变动,提交变动信息到
store
代码剖析
index.js
import push from "./push";
import connectRouter from './connectRouter'
import ConnectedRouter from './ConnectedRouter';
import routerMiddleware from './routerMiddleware'
export {
push,
connectRouter,
ConnectedRouter,
routerMiddleware,
}
constant.js
向外裸露用到的type
常量
export const LOCATION_CHANGE = "@@router/LOCATION_CHANGE"; // 路由变动
export const CALL_HISTORY_METHOD = "@@router/CALL_HISTORY_METHOD"; // 触发路由办法
push.js
封装咱们的push
办法,这里是返回一个action
信息,接下来的中间件能够截取到这个action
,并触发对应的method
操作
import * as TYPES from "./constant";
export default function(path){
return {
type: TYPES.LOCATION_CHANGE,
payload:{
method:"push",
path
}
}
}
routerMiddleware.js
routerMiddleware
是一个中间件,如下面所述,截取action
,如果是本人定义的type
,拦挡并触发对应的路由办法,否则执行下一个中间件
import * as TYPES from "./constant";
export default (history)=>(store)=>(next)=>(action)=>{
if (action.type === TYPES.LOCATION_CHANGE) {
const { method, path } = action.payload;
history[method](path);
} else {
next(action);
}
}
connectRouter.js
connectRouter
就是咱们记录信息的reducer
了,然而路由state
信息须要同步,就须要监听路由的变动,并dispatch
到store
中。
import * as TYPES from "./constant"
let initState = {}
export default function(history) {
return (state = initState,action)=>{
switch (action.type) {
case TYPES.CALL_HISTORY_METHOD:
return action.payload;
default:
return state;
}
}
}
ConnectedRouter.js
ConnectedRouter
的目标就是为了监听路由的变动,并触发store
的更新,这样路由就能做到同步更新了。
import * as TYPES from "./constant"
import React, { Component } from 'react'
import { Router } from "react-router";
import { ReactReduxContext }from "react-redux";
export default class ConnectedRouter extends Component {
static contextType = ReactReduxContext;
componentDidMount(){
this.unlisten = this.props.history.listen((payload)=>{
this.context.store.dispatch({
type: TYPES.CALL_HISTORY_METHOD,
payload
})
})
}
componentWillUnmount(){
this.unlisten();
}
render() {
const {history,children} = this.props;
return (
<Router history={history}>
{children}
</Router>
)
}
}
发表回复