ctrlplusb / react-universally

A starter kit for universal react applications.
MIT License
1.7k stars 244 forks source link

Having an issue with authenticated routes #467

Closed cigircii closed 6 years ago

cigircii commented 7 years ago

Hi there,

We are trying to create Authenticated Routes for our application. This functionality works inside the application if you go from page to page (client sided).

We're having an server sided routing issue. If you try to connect straight to an authenticated route, it keeps loading the page.

This is our Authenticated route component:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { loadUser } from '../../../actions/login';
import { setRedirectUrl } from '../../../actions/url';
import { Redirect } from 'react-router-dom';
import AsyncCounterRoute from '../AsyncCounterRoute'

@connect((store, ownProps) => ({
  isLoggedIn: store.login.isLoggedIn,
  currentURL: ownProps.location.pathname,
  userIsLoading: store.login.userIsLoading,
}))

class AuthRoute extends Component {
  constructor(props) {
    super(props);
  }

  componentDidMount() {
    const { dispatch, currentURL } = this.props;
  }

  componentWillMount() {
    this.props.dispatch(loadUser(localStorage.getItem('token')));
  }

  render() {
    console.log('props', this.props);
    if (!this.props.userIsLoading) {
      if (this.props.isLoggedIn) {
        return <this.props.component />;
      }else {
          this.props.dispatch(setRedirectUrl(this.props.currentURL));
          return <Redirect to="/login"/>;
      }
    }
    return null
  }
}

export default AuthRoute;

This is our index page where we added the routing for the pages.

        <Switch>
          <Route exact path="/" component={AsyncHomeRoute} />
          <AuthRoute path="/counter" component={AsyncCounterRoute} />
          <Route path="/login" component={AsyncLoginRoute} />
          <Route component={Error404} />
        </Switch>
strues commented 7 years ago

@cigircii Here's an example that should work for you


export const hasAccessToken = () => {
  const token = getToken();
  return !!token;
};

type ProtectedProps = {
  component: ReactElement,
  location: Object,
};

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

export type Props = {
  className: ?string,
  ui: Object,
  data: Object,
  location: Location,
};

type Location = {
  pathname: string,
  hash: ?string,
};

.....

        <Switch>
          <ProtectedRoute path="/protected" component={Protected} />
          <Route path="/" component={Page} />
          <Route component={Error404} />
        </Switch>
oyeanuj commented 7 years ago

@cigircii Seems like you are using Redux? If yes, definitely take a look at https://github.com/mjrussell/redux-auth-wrapper if you haven't. It provides a clean API to work with protected routes.