Cracs
Cracs

Reputation: 525

ReactJS protected route with API call

I'm trying to protect my routes in ReactJS. On each protected routes I want to check if the user saved in localStorage is good.

Below you can see my routes file (app.js) :

class App extends Component {
    render() {
        return (
            <div>
                <Header />
                <Switch>
                    <Route exact path="/" component={Home} />
                    <Route path="/login" component={Login} />
                    <Route path="/signup" component={SignUp} />
                    <Route path="/contact" component={Contact} />
                    <ProtectedRoute exac path="/user" component={Profile} />
                    <ProtectedRoute path="/user/person" component={SignUpPerson} />
                    <Route component={NotFound} />
                </Switch>
                <Footer />
            </div>
        );
    }
}

My protectedRoute file :

const ProtectedRoute = ({ component: Component, ...rest }) => (
    <Route {...rest} render={props => (
        AuthService.isRightUser() ? (
            <Component {...props} />
        ) : (
            <Redirect to={{
                pathname: '/login',
                state: { from: props.location }
            }}/>
        )
    )} />
);

export default ProtectedRoute;

And my function isRightUser. This function send a status(401) when the data aren't valid for the user logged :

async isRightUser() {
    var result = true;
    //get token user saved in localStorage
    const userAuth = this.get();

    if (userAuth) {
        await axios.get('/api/users/user', {
            headers: { Authorization: userAuth }
        }).catch(err => {
            if (!err.response.data.auth) {
                //Clear localStorage
                //this.clear();
            }

            result = false;
        });
    }

    return result;
}

This code is not working and I don't know really why. Maybe I need to call my function AuthService.isRightUser() with a await before the call and put my function async ?

How can I update my code to check my user before accessing a protected page ?

Upvotes: 2

Views: 4179

Answers (2)

f-CJ
f-CJ

Reputation: 4481

When you annotate a function with async like you did in AuthService.isRightUser() it returns a Promise and you are not treating the response of the method accordingly.

As you suggested, you could call the method AuthService.isRightUser() with await and annotate the function you are passing to the render property with async.

Or you could treat the response of AuthService.isRightUser() with a .then() and .catch() instead of the ternary operator

Upvotes: 0

Burak Gavas
Burak Gavas

Reputation: 1354

I had the same issue and resolved it by making my protected route a stateful class.

Inside switch I used

<PrivateRoute 
    path="/path"
    component={Discover}
    exact={true}
/>

And my PrivateRoute class is as following

class PrivateRoute extends React.Component {

    constructor(props, context) {
        super(props, context);

        this.state = {
            isLoading: true,
            isLoggedIn: false
        };

        // Your axios call here

        // For success, update state like
        this.setState(() => ({ isLoading: false, isLoggedIn: true }));

        // For fail, update state like
        this.setState(() => ({ isLoading: false, isLoggedIn: false }));

    }

    render() {

        return this.state.isLoading ? null :
            this.state.isLoggedIn ?
            <Route path={this.props.path} component={this.props.component} exact={this.props.exact}/> :
            <Redirect to={{ pathname: '/login', state: { from: this.props.location } }} />

    }

}

export default PrivateRoute;

Upvotes: 6

Related Questions