1 |
|
2 |
|
3 | export const TRANSITION = '@@router/TRANSITION'
|
4 | export const UPDATE_LOCATION = '@@router/UPDATE_LOCATION'
|
5 |
|
6 | const SELECT_STATE = state => state.routing
|
7 |
|
8 | function transition(method) {
|
9 | return arg => ({
|
10 | type: TRANSITION,
|
11 | method, arg
|
12 | })
|
13 | }
|
14 |
|
15 | export const routeActions = {
|
16 | push: transition('push'),
|
17 | replace: transition('replace'),
|
18 | go: transition('go'),
|
19 | goBack: transition('goBack'),
|
20 | goForward: transition('goForward')
|
21 | }
|
22 |
|
23 | function updateLocation(location) {
|
24 | return {
|
25 | type: UPDATE_LOCATION,
|
26 | location
|
27 | }
|
28 | }
|
29 |
|
30 |
|
31 |
|
32 | const initialState = {
|
33 | location: undefined
|
34 | }
|
35 |
|
36 | export function routeReducer(state = initialState, { type, location }) {
|
37 | if (type !== UPDATE_LOCATION) {
|
38 | return state
|
39 | }
|
40 |
|
41 | return { ...state, location }
|
42 | }
|
43 |
|
44 |
|
45 |
|
46 | export function syncHistory(history) {
|
47 | let unsubscribeHistory, currentKey, unsubscribeStore
|
48 | let connected = false, syncing = false
|
49 |
|
50 | function middleware(store) {
|
51 | unsubscribeHistory = history.listen(location => {
|
52 | currentKey = location.key
|
53 | if (syncing) {
|
54 |
|
55 | return
|
56 | }
|
57 |
|
58 | store.dispatch(updateLocation(location))
|
59 | })
|
60 |
|
61 | connected = true
|
62 |
|
63 | return next => action => {
|
64 | if (action.type !== TRANSITION || !connected) {
|
65 | return next(action)
|
66 | }
|
67 |
|
68 | const { method, arg } = action
|
69 | history[method](arg)
|
70 | }
|
71 | }
|
72 |
|
73 | middleware.listenForReplays =
|
74 | (store, selectRouterState = SELECT_STATE) => {
|
75 | const getRouterState = () => selectRouterState(store.getState())
|
76 | const { location: initialLocation } = getRouterState()
|
77 |
|
78 | unsubscribeStore = store.subscribe(() => {
|
79 | const { location } = getRouterState()
|
80 |
|
81 |
|
82 |
|
83 |
|
84 | if (!location) {
|
85 | history.transitionTo(initialLocation)
|
86 | return
|
87 | }
|
88 |
|
89 |
|
90 |
|
91 |
|
92 | if (location.key !== currentKey) {
|
93 | syncing = true
|
94 | history.transitionTo(location)
|
95 | syncing = false
|
96 | }
|
97 | })
|
98 | }
|
99 |
|
100 | middleware.unsubscribe = () => {
|
101 | unsubscribeHistory()
|
102 | if (unsubscribeStore) {
|
103 | unsubscribeStore()
|
104 | }
|
105 |
|
106 | connected = false
|
107 | }
|
108 |
|
109 | return middleware
|
110 | }
|