Last active
July 23, 2017 14:17
-
-
Save ArthurClemens/327dda481b9fd227ee86 to your computer and use it in GitHub Desktop.
Mithril routing with Redux. Fiddle: https://jsfiddle.net/ArthurClemens/dzqv0s4q/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// app/redux/action-creators.es6.js | |
import {SET_ROUTE} from 'app/redux/action-types'; | |
export const setRoute = (route) => { | |
return { | |
type: SET_ROUTE, | |
route | |
}; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// app/redux/action-types.es6.js | |
export const SET_ROUTE = 'SET_ROUTE'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// app/index/index.es6.js | |
import router from 'app/redux/router'; | |
import m from 'mithril'; | |
import {store, observeStore} from 'app/redux/store'; | |
const index = {}; | |
index.view = () => { | |
return m('div', [ | |
m('h1', [ | |
'path: ', | |
m.route() | |
]), | |
m('ul', [ | |
m('li', m('a', { | |
href: '/home', | |
config: m.route | |
}, 'Home')), | |
m('li', m('a', { | |
href: '/favorites', | |
config: m.route | |
}, 'Favorites')), | |
m('li', m('a', { | |
href: '/settings', | |
config: m.route | |
}, 'Settings')) | |
]) | |
]); | |
}; | |
m.route.mode = 'hash'; | |
const routes = { | |
'/': router(m.component(index)), | |
'/home': router(m.component(index)), | |
'/favorites': router(m.component(index)), | |
'/settings': router(m.component(index)) | |
}; | |
// To debug changes | |
observeStore(store, (state) => state.route.path, (path) => { | |
console.log("changed path", path); | |
}); | |
m.route(document.body, '/', routes); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// app/redux/reducers.es6.js | |
import {combineReducers} from 'redux'; | |
import {SET_ROUTE} from 'app/redux/action-types'; | |
const route = (state = {path: undefined}, action) => { | |
switch (action.type) { | |
case SET_ROUTE: | |
return action.route; | |
default: | |
return state; | |
} | |
}; | |
const app = combineReducers({ | |
route | |
// assuming more reducers are added here | |
}); | |
export default app; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// app/redux/router.es6.js | |
import m from 'mithril'; | |
import {store, observeStore} from 'app/redux/store'; | |
import {setRoute} from 'app/redux/action-creators'; | |
window.addEventListener((m.route.mode === 'hash') ? 'hashchange' : 'popstate', () => passiveRouteChange(window.location)); | |
observeStore(store, (state) => state.route, (route) => { | |
if (!route.path) { | |
return; | |
} | |
// Redirect with m.route() unless explicitly stated | |
// Calls from passiveDispatch do not redirect. | |
const redirect = (route.redirect === undefined || route.redirect); | |
if (redirect) { | |
m.route(route.path); | |
} | |
}); | |
const passiveDispatch = (path, redirect = false) => ( | |
store.dispatch(setRoute({ | |
path, | |
redirect | |
})) | |
); | |
const passiveRouteChange = (location) => { | |
const path = m.route.mode === 'hash' | |
? location.hash.substring(1) | |
: m.route.mode === 'search' | |
? location.search.substring(1) | |
: location.pathname; | |
if (path) { | |
passiveDispatch(path); | |
} | |
}; | |
/* | |
m.route wrapper | |
Call as: | |
const routes = { | |
'/home': router(m.component(home)) | |
}; | |
*/ | |
export default function(component) { | |
return { | |
controller: function() { | |
const currentPath = store.getState().route.path; | |
const newPath = m.route(); | |
if (newPath !== currentPath) { | |
passiveDispatch(newPath); | |
} | |
return new component.controller(); | |
}, | |
view: component.view | |
}; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {createStore} from 'redux'; | |
import app from 'app/redux/reducers'; | |
export const store = createStore(app, {}); | |
export const observeStore = (store, select, onChange) => { | |
let currentState; | |
const handleChange = () => { | |
let nextState = select(store.getState()); | |
if (nextState !== currentState) { | |
currentState = nextState; | |
onChange(currentState); | |
} | |
}; | |
const unsubscribe = store.subscribe(handleChange); | |
handleChange(); | |
return unsubscribe; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Assuming a setup of: