import React, { createContext, useEffect, useState, useContext, useMemo, useCallback } from "react"; import history from "browser-history"; import pathToRegexp from "path-to-regexp"; const RouterContext = createContext(); const Router = ({ children }) => { const [url, setUrl] = useState(window.location.pathname); useEffect(() => { history((e, url) => setUrl(url)); }, []); const go = url => { setUrl(url); history(url); }; const testUrl = useCallback( (path, exact) => { const re = pathToRegexp(exact ? path : path + "(.*)", [], { sensitive: false }); return { doesMatch: re.test(url), parts: re.exec(url) }; }, [url] ); const contextValue = { url, testUrl, go }; return ( {children} ); }; const Route = ({ path, exact, component: Component, children, ...componentProps }) => { const { testUrl } = useContext(RouterContext); const r = useMemo(() => testUrl(path, exact), [testUrl, path, exact]); if (r.doesMatch) { return Component ? ( ) : ( children ); } return null; }; const Link = ({ path, children }) => { const { go } = useContext(RouterContext); const onClick = () => { go(path); }; return {children}; }; const Redirect = ({ from, to }) => { const { go, testUrl } = useContext(RouterContext); const r = useMemo(() => testUrl(from, true), [testUrl, from]); if (r.doesMatch) { go(to); } return null; }; export { RouterContext, Router, Route, Redirect, Link };