Last active
November 4, 2018 15:49
-
-
Save acdlite/26628a2b3b7bdc76f805 to your computer and use it in GitHub Desktop.
Minimal router using existing React Router primitives
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
const history = createHistory(); | |
const router = createReactRouter(routes); | |
history.listen((location => { | |
router.match(location, (err, state, redirectInfo) => { | |
// Integrate with external state library (Redux), or render directly | |
React.render( | |
<RouterComponent {...state} />; | |
); | |
}); | |
}); | |
// On the server, just omit history | |
router.match(createLocation(path), (err, state, redirectInfo) => { | |
React.renderToString( | |
<RouterComponent {...state} />; | |
); | |
}); |
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
/** | |
* type RouterState = { | |
* activeRoutes: Array<Route>, | |
* params: Object | |
* } | |
*/ | |
import matchRoutes from './matchRoutes'; | |
import runTransitionHooks from './runTransitionHooks'; | |
/** | |
* Base createRouter() function with no React-specific functionality, | |
* because #modularity | |
*/ | |
export function createRouter(routes) { | |
let state; | |
function match(location, callback) { | |
matchRoutes(routes, location, (error, nextState) => { | |
if (!error) { | |
state = nextState; | |
} | |
callback(error, nextState); | |
}); | |
} | |
function getState() { | |
return state; | |
} | |
return { | |
match, | |
getState | |
}; | |
} | |
/** | |
* Router enhancer runs transition hooks when matching | |
*/ | |
export function useTransitionHooks(next) { | |
return routes => { | |
const router = next(routes); | |
function match(location, callback) { | |
const prevState = router.getState(); | |
router.match(location, (error, nextState) => { | |
if (error || nextState == null) { | |
callback(error, null); | |
return; | |
} | |
runTransitionHooks(prevState, nextState, (transitionError, redirectInfo) => { | |
if (error || redirectInfo) { | |
callback(error, null, redirectInfo); | |
} | |
callback(null, nextState); | |
}); | |
}); | |
} | |
return { | |
...router, | |
match | |
}; | |
}; | |
} | |
/** | |
* Router-creating function with transition hook functionality added | |
*/ | |
export const createReactRouter = useTransitionHooks(createRouter); |
And yeah I think with an API like this there's potential for a really nice middleware ecosystem, a la Redux.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Oh but you're right that
useTransitionHooks()
is a better name for that function. Nothing React-y about it.