git.fiddlerwoaroof.com
src/provider-api.js
77ace510
 import * as R from 'ramda';
5c5f8ac3
 import React, {useReducer, useEffect} from 'react';
 import PropTypes from 'prop-types';
77ace510
 
 const RouteContext = React.createContext(null);
 const ActionDispatcherContext = React.createContext(null);
 
 function RouteProvider({children, actionDispatcher, _window}) {
 
   const [route, updateRoute] = useReducer((state, action) =>
       R.omit(['type'], R.assoc('routeName', action.type, action))
     , {});
 
   useEffect(() => {
     return actionDispatcher.addActionListener(action => updateRoute(action));
   });
 
   useEffect(() => {
     actionDispatcher.receiveLocation(_window.location);
   });
 
   return (<ActionDispatcherContext.Provider value={actionDispatcher}>
     <RouteContext.Provider value={route}>
       {children}
     </RouteContext.Provider>
   </ActionDispatcherContext.Provider>);
 }
 
 RouteProvider.defaultProps = {
   _window: window ? window : null
 };
 
5c5f8ac3
 RouteProvider.propTypes = {
   _window: PropTypes.object,
   children: PropTypes.oneOfType([
     PropTypes.arrayOf(PropTypes.node),
     PropTypes.node
   ]),
   actionDispatcher: PropTypes.object
 };
 
 function getDisplayName(WrappedComponent) {
   return WrappedComponent.displayName || WrappedComponent.name || 'Component';
 }
 
77ace510
 function withRoute(Component) {
5c5f8ac3
   const routeAdded = ({children, ...restProps}) => {
77ace510
     return (<RouteContext.Consumer>
         {route =>
           <Component {...{...restProps, route}}>{children}</Component>
         }
       </RouteContext.Consumer>
     )
5c5f8ac3
   };
   routeAdded.displayName = `withRoute(${getDisplayName(Component)})`
   routeAdded.propTypes = {
     children: PropTypes.oneOfType([
       PropTypes.arrayOf(PropTypes.node),
       PropTypes.node
     ])
   };
   return routeAdded;
77ace510
 }
 
 function RouteLink({route, params, children, ...props}) {
   const action = {
     type: route, ...params
   };
   return <ActionDispatcherContext.Consumer>{
     dispatcher => {
       const url = dispatcher.pathForAction(action);
       return <a
         onClick={(ev) => {
           ev.preventDefault();
df6a63f6
           dispatcher.receiveAction(action, true);
77ace510
         }}
         href={url} {...props}>{children}</a>
     }
   }
   </ActionDispatcherContext.Consumer>;
 }
 
5c5f8ac3
 RouteLink.propTypes = {
   route: PropTypes.string,
   params: PropTypes.object,
   children: PropTypes.oneOfType([
     PropTypes.arrayOf(PropTypes.node),
     PropTypes.node
   ]),
 };
 
77ace510
 export {RouteProvider, withRoute, RouteLink};