Alex
Alex

Reputation: 1046

Custom Route with React Router 4

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

Answers (3)

Bernstein Yaakov
Bernstein Yaakov

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

Alex
Alex

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

Dekel
Dekel

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

Related Questions