Skip to content

Instantly share code, notes, and snippets.

@scorsi
Created February 27, 2020 15:03
Show Gist options
  • Save scorsi/2255be4b2cfef007c288d35a25721e08 to your computer and use it in GitHub Desktop.
Save scorsi/2255be4b2cfef007c288d35a25721e08 to your computer and use it in GitHub Desktop.
My React Router using hooks
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 (
<RouterContext.Provider value={contextValue}>
{children}
</RouterContext.Provider>
);
};
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 ? (
<Component {...componentProps} parts={r.parts} />
) : (
children
);
}
return null;
};
const Link = ({ path, children }) => {
const { go } = useContext(RouterContext);
const onClick = () => {
go(path);
};
return <a onClick={onClick}>{children}</a>;
};
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 };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment