ed94133
ed94133

Reputation: 1595

How can I set up a React Router auth flow?

I'm new to React and having trouble creating a simple auth flow using GraphQL, following the React Router example.

I would like / to be my login screen, which appears only if the user is logged out. If not, the app should redirect to /dashboard (which should otherwise be inaccessible). Here's what I have, which generates an infinite loop after authentication:

class App extends Component {
    constructor(props) {
        super(props);

        this.state = {
            authenticated: false
        }
    }

    renderButtons () {
        if (this.state.authenticated) {
            return (
                <a>Logout</a>
            )
        }
        return null;
    }

    componentWillReceiveProps({ data }) {
        if (this.props.data.loading && !data.loading) {
            if (data.loggedInUser.id && !this.state.authenticated) {
                this.setState({authenticated: true});
            } else if (this.state.authenticated) {
                this.setState({authenticated: false});
            }
        }
    }

    render () {
        return (
            <div className="container">
                <nav>
                    {this.renderButtons()}
                </nav>
                <GatingRoute path="/" component={LoginPage} isAuthenticated={this.state.authenticated} newPath="/dashboard" />
                <PrivateRoute path="/dashboard" component={Dashboard} isAuthenticated={this.state.authenticated} />
            </div>
        );
    }
};

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

const GatingRoute = ({ component: Component, isAuthenticated, newPath, ...rest}) => (
    <Route
      {...rest}
      render={props => (
        isAuthenticated
        ? (
            (<Redirect to={{ pathname: newPath, state: { from: props.location } }} />)
        )
        : 
        <Component {...props} />
      )}
    />
    );

export default graphql(query, { options: {fetchPolicy: 'network-only'}})(withRouter(App));

Upvotes: 1

Views: 500

Answers (1)

Joshua Underwood
Joshua Underwood

Reputation: 927

Rather than working the way you are now...

In your parent component where you have your routes do the following

<BrowserRouter>
    <Route path=“/“ exact         render={ ( props ) =>
 props.user.loggedIn ? <Dashboard /> : <LoginForm />
}/>
</BrowserRouter>

This assumes the component that renders your router knows of the user status.

My apologies for the poor formatting on mobile.

Upvotes: 2

Related Questions