I\'m trying to pass a variable of type React.Component (or React.FunctionComponent) into a Route, like this:
import React from \'react\';
import { Route } from \
I have encountered this a couple of times. Try these:
PrivateRoute
as React.FC<Props>
React.ElementType
The ultimate truth about React types comes from the docs
Edit: React.ReactType (deprecated) -> React.ElementType
This is late but in case someone didn't want a solution but an explanation, let's talk about this error using an example to demonstrate it
function PaymentPage(){
return <div>Payment Page</div>
}
say we want to create a dynamic payment form, if the query parameter is with=stripe so we assume he wants to pay with stripe, if it's with razorpay we assume it, ...etc.
we then do something like
function PaymentPage(){
const router = useRouter;
const {with} = router.query;
let GatewayComponent: Gateway | null = null;
switch(with){
case 'stripe':
return <StripeGateway/>
case 'razorpay':
return <RazorpayGateway/>
}
return <GatewayComponent/>
}
Running this, we get
JSX element type 'Component' does not have any construct or call signatures.
What happens?
GatewayComponent
is a constructor, but it's not, it's a variable holding JSXSo basically, expects x to be a constructor of any type, either a function or a class, if it's a function, the function is the render function, if it's a class, it needs a render method.
function PaymentPage(){
const router = useRouter;
const {with} = router.query;
let gateway: Gateway | null = null;
switch(with){
case 'stripe':
return <StripeGateway/>
case 'razorpay':
return <RazorpayGateway/>
}
return <React.Fragment> {gateway} </React.Fragment>
}
Because gateway holds JSX, not a constructor that returns JSX
function PaymentPage(){
const router = useRouter;
const {with} = router.query;
let GatewayComponent: Gateway | null = null;
switch(with){
case 'stripe':
return () => <StripeGateway/>
case 'razorpay':
return () => <RazorpayGateway/>
}
return <GatewayComponent/>
}
Now it's a constructor, we can use it as a component right now.
Formally, you pass the constructor and not the instance.
Even later to the party, but what worked for me is this:
interface PrivateRouteProps extends Omit<RouteProps, "component"> {
component: React.ElementType;
// any additional vars
}
PrivateRoute: React.FC<PrivateRouteProps> = ({
component: Component,
...rest
}) => {
// render code
}
I was able to resolve the error by typing my component as follows:
...
export function withApollo (PageComponent: () => JSX.Element) {
const WithApollo = <T extends object>(props: T) => {
...
Late to the party, with "@types/react-router-dom": "^4.3.4"
and "@types/react": "16.9.1"
, and if you're using RouteProps
, you will probably get the same error.
JSX element type 'Component' does not have any construct or call signatures. [2604]
That's because, in the RouteProps
interface, the component
is defined as optional, hence it might be undefined.
export interface RouteProps {
location?: H.Location;
component?: React.ComponentType<RouteComponentProps<any>> | React.ComponentType<any>;
render?: ((props: RouteComponentProps<any>) => React.ReactNode);
children?: ((props: RouteChildrenProps<any>) => React.ReactNode) | React.ReactNode;
path?: string | string[];
exact?: boolean;
sensitive?: boolean;
strict?: boolean;
}
Simply check for if the component
is falsy will fix it.
function PrivateRoute({ component: Component, ...rest }: RouteProps) {
if (!Component) return null;
return (
<Route
{...rest}
render={props =>
fakeAuth.isAuthenticated ? (
<Component {...props} />
) : (
<Redirect
to={{
pathname: "/login",
state: { from: props.location }
}}
/>
)
}
/>
);
}