Reputation: 1046
I am after creating a custom Route component with React. I came across the following solution I found but I am getting the error after.
import * as React from 'react';
import { Route, Redirect } from 'react-router-dom';
import { isLoggedIn } from '../../modules/AuthService';
export class AuthRequiredRoute extends Route {
render() {
if (!isLoggedIn()) {
return <Redirect to='/login' />
} else {
return <this.props.component />
}
}
}
Error: JSX element type 'this.props.component' does not have any construct or call signatures.
Following is the way I am going to use the component:
<AuthRequiredRoute exact path='/' component={Home} />
Can anybody help me with resolving this issue please?
Upvotes: 1
Views: 6286
Reputation: 11
Why not use the abilities of polymorphism? worked perfect for me:
export class ProtectedRoute extends Route {
render() {
if (!isLoggedIn()) {
return <Redirect to='/login' />
} else {
return super.render();
}
}
}
In OO concepts(although we are JS world...) the render of Route is a black box and I assume we wont be able to exactly to code the the base render. All we want is to add behavior to A Route element for a specific behavior(not logged in) so all we to add is what we want to extend not the basic behavior. Furthermore even if for some reason(might say not so smart) I would copy exactly the contents of the basic render of Route. if one day Route would be updated I would lose all those added features.
Upvotes: 1
Reputation: 1046
I managed to fix the issue by going with a different solution.
I created a HOC module named Authenticated.tsx with the below code:
import * as React from 'react';
import { withRouter, RouteComponentProps } from 'react-router-dom';
import { isLoggedIn } from '../../modules/AuthService';
export function Authenticated(BaseComponent) {
class AuthenticatedComponent extends React.Component<RouteComponentProps<any>, {}> {
componentWillMount() {
this.checkAuthentication(this.props);
}
componentWillReceiveProps(nextProps) {
if (nextProps.location !== this.props.location) {
this.checkAuthentication(nextProps);
}
}
checkAuthentication(params) {
const { history } = params;
if (!isLoggedIn()) {
history.replace({ pathname: '/login' });
}
}
render() {
return <BaseComponent {...this.props} />;
}
}
return withRouter(AuthenticatedComponent);
}
Then I used it this way in my routes.tsx component:
import { Authenticated } from './components/utils/Authenticated';
export const routes = <Layout>
<Route exact path='/' component={Authenticated(Home)} />
<Route path='/login' component={Login} />
</Layout>;
Upvotes: 2
Reputation: 62576
Use a Component
variable to construct a jsx component:
export class AuthRequiredRoute extends Route {
render() {
if (!isLoggedIn()) {
return <Redirect to='/login' />
} else {
let Component = this.props.component;
return <Component />
}
}
}
Upvotes: 0