diff --git a/src/action-router.js b/src/action-router.js index 0d92ad2..84dde1b 100644 --- a/src/action-router.js +++ b/src/action-router.js @@ -281,7 +281,7 @@ function constructPath(match) { return resultParts.join("/"); } -function createActionDispatcher(routesConfig, window) { +function createActionDispatcher(routesConfig, _window = window) { const { compiledActionMatchers, compiledRouteMatchers } = compileRoutes( routesConfig ); @@ -298,6 +298,7 @@ function createActionDispatcher(routesConfig, window) { let actionListeners = []; let currentPath = null; + let currentAction = null; function ifPathChanged(newPath, cb) { if (currentPath !== newPath) { @@ -307,7 +308,12 @@ function createActionDispatcher(routesConfig, window) { } const actionDispatcher = { - + get currentPath() { + return currentPath; + }, + get currentAction() { + return currentAction; + }, pathForAction, //hook for everything to get action on route change @@ -330,6 +336,8 @@ function createActionDispatcher(routesConfig, window) { const action = actionForLocation(location); + currentAction = action; + if (action) { actionListeners.forEach(cb => cb(action)); } @@ -344,7 +352,10 @@ function createActionDispatcher(routesConfig, window) { if (newPath) { ifPathChanged(newPath, () => { - window.history.pushState({}, "", newPath); + currentAction = action; + + _window.history.pushState({}, "", newPath); + if(fireCallbacks) { actionListeners.forEach(cb => cb(action)); } @@ -354,7 +365,7 @@ function createActionDispatcher(routesConfig, window) { }; - window.addEventListener("urlchanged", actionDispatcher); + _window.addEventListener("urlchanged", actionDispatcher); return actionDispatcher; } diff --git a/src/provider-api.js b/src/provider-api.js index 9e01b5f..2ca0da6 100644 --- a/src/provider-api.js +++ b/src/provider-api.js @@ -2,24 +2,24 @@ import * as R from 'ramda'; import React, {useReducer, useEffect} from 'react'; import PropTypes from 'prop-types'; +import {createActionDispatcher} from "./action-router"; + const RouteContext = React.createContext(null); const ActionDispatcherContext = React.createContext(null); -function RouteProvider({children, actionDispatcher, _window}) { +function RouteProvider({children, routeDispatcher, _window}) { - const [route, updateRoute] = useReducer((state, action) => - R.omit(['type'], R.assoc('routeName', action.type, action)) - , {}); + const [route, updateRoute] = useReducer((state, action) => action, {}); useEffect(() => { - return actionDispatcher.addActionListener(action => updateRoute(action)); + return routeDispatcher.addRouteListener(updateRoute); }); useEffect(() => { - actionDispatcher.receiveLocation(_window.location); + routeDispatcher.receiveLocation(_window.location); }); - return ( + return ( {children} @@ -36,7 +36,7 @@ RouteProvider.propTypes = { PropTypes.arrayOf(PropTypes.node), PropTypes.node ]), - actionDispatcher: PropTypes.object + routeDispatcher: PropTypes.object }; function getDisplayName(WrappedComponent) { @@ -89,4 +89,28 @@ RouteLink.propTypes = { ]), }; -export {RouteProvider, withRoute, RouteLink}; +function routeToAction(route) { + return R.omit(['routeName'], R.assoc('type', route.routeName, action)) +} +function actionToRoute(action) { + return R.omit(['type'], R.assoc('routeName', action.type, action)) +} + +function createRouteDispatcher(routesConfig, _window = window) { + const actionDispatcher = createActionDispatcher(routesConfig, _window); + + actionDispatcher.receiveRoute = (route) => actionDispatcher.receiveAction(routeToAction(route)); + actionDispatcher.addRouteListener = (cb) => actionDispatcher.addActionListener((action) => cb(actionToRoute(action))); + + Object.defineProperty(actionDispatcher, "currentRoute", { + enumerable: true, + writable: false, + get: function() { + return actionToRoute(this.currentAction) + } + }); + + return actionDispatcher; +} + +export {RouteProvider, withRoute, RouteLink, createRouteDispatcher};