connected-react-router
这个库帮我们实现了在 redux
中操作路由方法,并将路由变化的信息同步在 redux
的 store
中。
实现流程
actions
封装push
、replace
、go
等主要方法middleware
拦截actions
信息,触发封装好的action
方法reducer
新增router
的state信息ConnectedRouter
组件监听路由变化,更新路由信息到store
依赖库和目录结构
依赖库
目录结构
- 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 (
{children}
)
}
}