UNPKG

1.73 kBJavaScriptView Raw
1import { AppDataContext } from '@optimistdigital/create-frontend/universal-react';
2import { BrowserRouter } from 'react-router-dom';
3import { StaticRouter, withRouter, matchPath } from 'react-router';
4import React from 'react';
5
6function usePrevious(value) {
7 const ref = React.useRef();
8 React.useEffect(() => {
9 ref.current = value;
10 });
11 return ref.current;
12}
13
14const RouteChangeListener = withRouter(({ children, location, onChange }) => {
15 const prevLocation = usePrevious(location);
16
17 React.useEffect(() => {
18 if (
19 !prevLocation ||
20 `${location.pathname}${location.search}` !== `${prevLocation.pathname}${prevLocation.search}`
21 ) {
22 onChange && onChange(location);
23 }
24 // eslint-disable-next-line react-hooks/exhaustive-deps
25 }, [location, onChange]);
26 return children;
27});
28
29export default function Router({ children, ...passthrough }) {
30 const appData = React.useContext(AppDataContext);
31
32 if (__TARGET__ === 'web') {
33 return (
34 <BrowserRouter {...passthrough}>
35 <RouteChangeListener children={children} onChange={appData.onRouteChange} />
36 </BrowserRouter>
37 );
38 }
39
40 /**
41 * Server-side render
42 */
43 return (
44 <StaticRouter {...passthrough} location={appData.url} context={appData.serverContext}>
45 {children}
46 </StaticRouter>
47 );
48}
49
50export async function getRouteData(location, routes, backendData) {
51 const route = routes.find(x => matchPath(location.pathname, { exact: true, ...x }));
52
53 let updater;
54 if (route && route.component && route.component.getPageData) {
55 updater = await route.component.getPageData(location, matchPath(location.pathname, route).params, backendData);
56 }
57
58 return updater || (prevState => prevState);
59}