解析 connected-react-router

connected-react-router這個庫幫咱們實現了在 redux 中操做路由方法,並將路由變化的信息同步在 reduxstore 中。react

實現流程

  • actions 封裝 pushreplacego等主要方法
  • 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常量git

export const LOCATION_CHANGE = "@@router/LOCATION_CHANGE"; // 路由變化
export const CALL_HISTORY_METHOD = "@@router/CALL_HISTORY_METHOD"; // 觸發路由方法

push.js

封裝咱們的push方法,這裏是返回一個action信息,接下來的中間件能夠截取到這個action,並觸發對應的method操做github

import * as TYPES from "./constant";

export default function(path){
  return {
    type: TYPES.LOCATION_CHANGE,
    payload:{
      method:"push",
      path
    }
  }
}

routerMiddleware.js

routerMiddleware是一箇中間件,如上面所述,截取action,若是是本身定義的type,攔截並觸發對應的路由方法,不然執行下一個中間件redux

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信息須要同步,就須要監聽路由的變化,並dispatchstore中。react-router

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的更新,這樣路由就能作到同步更新了。this

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>
    )
  }
}
相關文章
相關標籤/搜索