Analysis of connected react router

Time:2020-10-25

connected-react-routerThis library helps us realize thereduxThe routing method is operated in, and the route change information is synchronized in thereduxOfstoreMedium.

Implementation process

  • actionsencapsulationpushreplacegoAnd so on
  • middlewareinterceptactionsInformation, trigger, packagedactionmethod
  • reducernewly addedrouterState information for
  • ConnectedRouterThe component monitors the route changes and updates the routing information to thestore

Dependency library and directory structure

Dependency Library

  • history
  • react-router

directory structure

  • index.js //Entry file
  • constant.js //Actions constant
  • push.js //Only the push method in history is encapsulated here, and the others are similar
  • connectRouter.js //Information of synchronous route change in reducer
  • routerMiddleware.js //Middleware, blocking action to trigger route update
  • ConnectedRouter.js //Component, which is mainly used to listen for route changes and submit change information tostore

code analysis

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

For external exposuretypeconstant

export const LOCATION_ CHANGE = "@@router/LOCATION_ Change "; // route change
export const CALL_ HISTORY_ METHOD = "@@router/CALL_ HISTORY_ Method "; // trigger routing method

push.js

Encapsulating ourpushMethod, which returns aactionThe next middleware can intercept this informationactionAnd trigger the correspondingmethodoperation

import * as TYPES from "./constant";

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

routerMiddleware.js

routerMiddlewareIs a middleware, as described above, interceptsaction, if it’s self-definedtype, intercept and trigger the corresponding routing method, otherwise execute the next middleware

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

connectRouterThat’s where we record informationreducerYes, but routingstateIf the information needs to be synchronized, it is necessary to monitor the route changes, anddispatchreachstoreMedium.

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

ConnectedRouterIn order to monitor route changes and triggerstoreIn this way, the route can be updated synchronously.

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>
    )
  }
}