Skip to content

Instantly share code, notes, and snippets.

@Osara12
Forked from ajitid/AliveAbleRoutes.tsx
Created January 12, 2023 15:36
Show Gist options
  • Save Osara12/f2f45c6eb9254eed7d4cea104d0ba1d3 to your computer and use it in GitHub Desktop.
Save Osara12/f2f45c6eb9254eed7d4cea104d0ba1d3 to your computer and use it in GitHub Desktop.
Keep alive routes

Hey, it does not passes route context so router's hooks and outlet component won't work. So this code, at least for now, is pretty useless.

Uses React Router v6

Usage

Before:

<Routes>
 <Route path="/" element={<Home />} />
 <Route path="/contacts" element={<Contacts />} />
</Routes>

After:

<AliveAbleRoutes>
 <Route path="/" element={<Home />} />
 <KeepAliveRoute path="/contacts" element={<Contacts />} />
</AliveAbleRoutes>
import React, { ReactElement, useState, useLayoutEffect } from 'react';
import { Routes, Route } from 'react-router-dom';
import type { RoutesProps, RouteProps } from 'react-router';
const AliveAbleRoutes = ({ children, ...props }: RoutesProps) => {
const routes = React.Children.toArray(children);
const keepAliveRoutes = routes.filter((route) => {
if (!React.isValidElement(route)) return false;
return route.type === KeepAliveRoute;
}) as ReactElement[];
const normalRoutes = routes.filter((route) => {
if (!React.isValidElement(route)) return false;
return route.type !== KeepAliveRoute;
}) as ReactElement[];
return (
<>
{keepAliveRoutes.map((route) => {
return (
<DisplayRoute key={route.key} {...route.props} routesProps={props} />
);
})}
<Routes {...props} children={normalRoutes} />
</>
);
};
interface DisplayRouteProps extends RouteProps {
routesProps: RoutesProps;
}
const DisplayRoute = ({
element,
routesProps,
...props
}: DisplayRouteProps) => {
const [show, setShow] = useState(false);
return (
<>
<div style={{ display: show ? 'unset' : 'none' }}>{element}</div>
<Routes {...routesProps}>
<Route
{...props}
element={<RouteMatchInformant onRouteMatchChange={setShow} />}
/>
</Routes>
</>
);
};
interface RouteMatchInformantProps {
onRouteMatchChange: (matches: boolean) => void;
}
const RouteMatchInformant = ({
onRouteMatchChange,
}: RouteMatchInformantProps) => {
useLayoutEffect(() => {
onRouteMatchChange(true);
return () => {
onRouteMatchChange(false);
};
}, [onRouteMatchChange]);
return null;
};
export const KeepAliveRoute = (props: RouteProps) => null;
export default AliveAbleRoutes;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment