Once you add redux simple router (or redux router) you have two places in your state that need to be kept in synch.
import { combineReducers } from 'redux'
import { routeReducer } from 'redux-simple-router'
import tree from './tree'
//reducers/index.js
const rootReducer = combineReducers({
tree: tree,
routing: routeReducer
})
export default rootReducer
Now every time you change tree you need to update the routing part, that's easy because your action creators may push a new state into the browser history.
The other way around, changing the URL and reduce correctly is a bit more complex because the router dispatches only one action (UPDATE_LOCATION if using redux-simple-router) and based on this action you need to reduce your state correctly.
Matching -and sometimes parsing- the url in your reducers is something that feels wrong, it is a logic that doesn't belong to the reducer.
Sagas in redux are an a way to listen for redux actions and spawn side effects accordingly. I've created a couple of sagas in sagas/index.js file.
The first one retriveNode watches for the RETRIEVE_NODE an action that I dispatch on the connected components, once the action is fired it executes in order some side effects, one of them being the url change provided by the push function.
Now we need to tackle another problem, what happens when someone changes the url like when I click the back or forward button on the browser?
In that case the routing part of our state changes but the tree part remains the same. The solution is in the other saga called urlChanged.
I listen to the UPDATE_LOCATION action and check if this action has been a POP, a POP action is our way to say: Did this action occur has a result of a back / forward navigation or it was intenionally pushed. This prevents executing ina loop both sagas.
Once the url changed as a result of the back / forward button we retreive the node, this will wake up the retriveNode saga and re build our state correctly.