作用

加强了React Router库中history这个实例,以允许将history中接受到的变化反应到state中去

用法

  1. import React from "react";
  2. import ReactDOM from "react-dom";
  3. import { createStore, combineReducers } from "redux";
  4. import { Provider } from "react-redux";
  5. import { Router, Route, browserHistory } from "react-router";
  6. import { syncHistoryWithStore, routerReducer,push,routerMiddleware,applyMiddleware } from "react-router-redux";
  7. import reducers from "<project-path>/reducers";
  8. const history = syncHistoryWithStore(browserHistory, store)
  9. const middleware = routerMiddleware(browserHistory)
  10. const store = createStore(
  11. combineReducers({
  12. ...reducers,
  13. routing: routerReducer,
  14. }),
  15. applyMiddleware(middleware)
  16. );
  17. // 注册listen监听函数
  18. history.listen(location => analyticsService.track(location.pathname))
  19. ReactDOM.render(
  20. <Provider store={store}>
  21. { /* Tell the Router to use our enhanced history */ }
  22. <Router history={history}>
  23. <Route path="/" component={App}>
  24. <Route path="foo" component={Foo}/>
  25. <Route path="bar" component={Bar}/>
  26. </Route>
  27. </Router>
  28. </Provider>,
  29. document.getElementById('mount')
  30. )
  31. // 路由跳转
  32. store.dispatch(push('/foo'))

syncHistoryWithStore源码

  1. 包装原生history
  2. 注册listen监听函数(触发dispatch更新store.location)
  3. 修改listen监听函数(通过store.subscribe实现) ```typescript

// 当locaiton改变的时候dispatch const handleLocationChange = (location) => { store.dispatch({ type: LOCATION_CHANGE, payload: location, }); };

// 返回取消订阅的函数 unsubscribeFromHistory = history.listen(handleLocationChange);

// 返回强化后的history,增强listen方法,通过store.subscribe监听location变化 return { …history, // 重写listen方法 listen(listener) { let lastPublishedLocation = getLocationInStore(true);

// 对比location,通过store订阅控制listener执行
let unsubscribed = false;
const unsubscribeFromStore = store.subscribe(() => {
  const currentLocation = getLocationInStore(true);
  if (currentLocation === lastPublishedLocation) {
    return;
  }
  lastPublishedLocation = currentLocation;
  if (!unsubscribed) {
    listener(lastPublishedLocation);
  }
});

return () => {
  unsubscribed = true;
  unsubscribeFromStore();
};

}, // 取消listen订阅 unsubscribe() { if (adjustUrlOnReplay) { unsubscribeFromStore(); } unsubscribeFromHistory(); }, };

push源码
```typescript
function updateLocation(method) {
  return (...args) => ({
    type: CALL_HISTORY_METHOD,
    payload: { method, args }
  })
}

/**
 * 重写原生history api
 * 通过routerMiddleware捕获参数,调用原生的history api
 */
export const push = updateLocation('push')


// ***********************
export default function routerMiddleware(history) {
  return () => next => action => {
    if (action.type !== CALL_HISTORY_METHOD) {
      return next(action)
    }

    const { payload: { method, args } } = action
    history[method](...args)
  }
}