RouteProps does not match react-router's RouteProps
mellis481 opened this issue · comments
I'm working to create a protected route component in my Preact app. This can be done in a React app that uses react-router like this:
import React from 'react';
import { Redirect, Route, RouteProps } from 'react-router-dom';
interface OwnProps extends RouteProps {}
export const ProtectedRoute: React.FC<OwnProps> = ({ component: Component, ...rest }) => {
const isAuthenticated = checkIsAuthenticated();
return (
<Route
render={(props) =>
isAuthenticated && Component ? <Component {...props} /> : <Redirect to="/logout" />
}
/>
);
};
In react-router, RouteProps
is defined like this and does not use generics or require a type to be defined:
export interface RouteProps<
Path extends string = string,
Params extends { [K: string]: string | undefined } = ExtractRouteParams<Path, string>
> {
location?: H.Location;
component?: React.ComponentType<RouteComponentProps<any>> | React.ComponentType<any>;
render?: (props: RouteComponentProps<Params>) => React.ReactNode;
children?: ((props: RouteChildrenProps<Params>) => React.ReactNode) | React.ReactNode;
path?: Path | readonly Path[];
exact?: boolean;
sensitive?: boolean;
strict?: boolean;
}
I'm trying to use this code to create the protected route component in my Preact app like this:
import { FunctionalComponent, h } from 'preact';
import { RouteProps } from 'preact-router';
interface OwnProps extends RouteProps { }
export const ProtectedRoute: FunctionalComponent<OwnProps> = ({ component: Component, ...rest }) => {
const isAuthenticated = checkIsAuthenticated();
return isAuthenticated && Component ? <Component {...rest} /> : <Redirect to="/logout" />;
};
This results in a type/compilation error because preact-router defines RouteProps
like this:
export interface RouteProps<Props> extends RoutableProps {
component: AnyComponent<Props>;
}
Why does preact-router's RouteProps
not match react-router's RouteProps
?
If you reference the readme:
💁 Note: This is not a preact-compatible version of React Router. preact-router is a simple URL wiring and does no orchestration for you.
If you're looking for more complex solutions like nested routes and view composition, react-router works great with preact as long as you alias in preact/compat.
It doesn't match because it's not intended to.
Here's an example of a type-safe way to do an authenticated route:
import { FunctionalComponent, h, VNode } from 'preact';
import { useEffect } from 'preact/hooks';
import { Route, route, Router } from 'preact-router';
const AuthenticatedRoute = (props: { path: string; component: FunctionalComponent<any> }): VNode => {
const isAuthenticated = checkIsAuthenticated();
useEffect(() => {
if (!isAuthenticated) route('/auth/login', true);
}, [isAuthenticated]);
return <Route {...props} />;
};
const App: FunctionalComponent = () => {
return (
<div id="app">
<Router>
<AuthenticatedRoute path="/" component={Home} />
</Router>
</div>
);
};