S
SolidJS5mo ago
MattHat

Creating a <ProtectedRoute/> component to use with solid router

Hi, Currently i have this which results in a Uncaught Error: <A> and 'use' router primitives can be only used inside a Route. ProtectedRoute.tsx:
...
import { useAuth } from "@/components/AuthContext";

export const ProtectedRoute: Component<ProtectedRouteProps> = (props) => {
const { component: ProtectedComponent, path } = props;
const auth = useAuth();
const location = useLocation();

return (
<Route
path={path}
component={(routeProps: RouteProps<string>) => {
return (
<Switch fallback={<Navigate href="/login" state={{ from: location.pathname }} />}>
<Match when={auth.isLoading()}>
<div>Loading...</div>
</Match>
<Match when={auth.isAuthenticated()}>
<ProtectedComponent {...routeProps} />
</Match>
</Switch>
);
}}
/>
);
};
...
import { useAuth } from "@/components/AuthContext";

export const ProtectedRoute: Component<ProtectedRouteProps> = (props) => {
const { component: ProtectedComponent, path } = props;
const auth = useAuth();
const location = useLocation();

return (
<Route
path={path}
component={(routeProps: RouteProps<string>) => {
return (
<Switch fallback={<Navigate href="/login" state={{ from: location.pathname }} />}>
<Match when={auth.isLoading()}>
<div>Loading...</div>
</Match>
<Match when={auth.isAuthenticated()}>
<ProtectedComponent {...routeProps} />
</Match>
</Switch>
);
}}
/>
);
};
Index.tsx:
const queryClient = new QueryClient();

const App = () => (
<Router>
<Suspense fallback={<div>Loading...</div>}>
<QueryClientProvider client={queryClient}>
<AuthProvider>
<Route path="/login/:orgUsername?" component={Login} />
<Route path="*" component={NotFound} />
<Layout>
<ProtectedRoute path="/" component={Home} />
<ProtectedRoute path="/order" component={Order} />
<ProtectedRoute path="/order/:id" component={Status} />
</Layout>
<ToastRegion>
<ToastList />
</ToastRegion>
</AuthProvider>
</QueryClientProvider>
</Suspense>
</Router>
);
const queryClient = new QueryClient();

const App = () => (
<Router>
<Suspense fallback={<div>Loading...</div>}>
<QueryClientProvider client={queryClient}>
<AuthProvider>
<Route path="/login/:orgUsername?" component={Login} />
<Route path="*" component={NotFound} />
<Layout>
<ProtectedRoute path="/" component={Home} />
<ProtectedRoute path="/order" component={Order} />
<ProtectedRoute path="/order/:id" component={Status} />
</Layout>
<ToastRegion>
<ToastList />
</ToastRegion>
</AuthProvider>
</QueryClientProvider>
</Suspense>
</Router>
);
3 Replies
Brendonovich
Brendonovich5mo ago
There's a few things here you'll want to change Destructuring props like in ProtectedRoute isn't supported in Solid <Router> should only have <Route> elements as its children, move the suspense and context providers outside of it Layout is a nested layout that should be in a <Route> of its own like PageWrapper in this example https://docs.solidjs.com/solid-router/concepts/layouts#nested-layouts Personally i'd move the ProtectedRoute logic into Layout so that it only has to be handled once, rather than on each navigation
MattHat
MattHatOP5mo ago
Thank you! Can't figure out what type i should use for the props in function PageWrapper(props). First tought was JSX.Element but that does not work.
Brendonovich
Brendonovich5mo ago
RouteSectionProps
Want results from more Discord servers?
Add your server