1
votes

I am trying to apply protected route using private route method in my graphql react app. I am using apollo client 2.

The private route works as intended, that is it protects / prevents someone from manually entering url (in this case /surveys). However, when the page is reloaded or refreshed manually, graphql query will initially return an empty object data (when user is logged in) or undefined data. Because of this, the condition for redirect inside the private route is applied hence the client is redirected to the "/" path. Is there anyway around this? Here is my app and my private route code:

/* app.js */
....imports

const WHOAMI = gql`
  query whoAmI {
    whoAmI {
      _id
      email
    }
  }
`;

class App extends Component {
  render() {
    return (
      <div>
        <BrowserRouter>
          <div>
            <Header />
            <Query query={WHOAMI}>
              {({ loading, error, data }) => {
                // console.log(data);
                return (
                  <div className="container">
                    <div className="col s12 center-align">
                      <Switch>
                        <Route path="/surveys/new" component={SurveyNew} />
                        <PrivateRoute
                          path="/surveys"
                          userId={data.whoAmI}
                          component={SurveyList}
                        />
                        <Route path="/" exact component={LandingPage} />
                      </Switch>
                    </div>
                  </div>
                );
              }}
            </Query>
          </div>
        </BrowserRouter>
      </div>
    );
  }
}

export default App;

and my PrivateRouter file

...imports 

const PrivateRoute = ({ component: Component, userId, ...rest }) => (  
  <Route {...rest} render={props => (
    !userId || userId === 'undefined' ? (
      <Redirect to={{
        pathname: '/'
        }}
      />
    ) : (
      <Component {...props} />
    )
  )} />
);


export default PrivateRoute
1

1 Answers

-1
votes

I have probably the same architecture and I do

class App extends Component {
  constructor (...args) {
    super(...args)

    this.state = {
      user: {},
      loading: true
    }
  }

  componentDidMount() {
    fetchUser()
      .then(user => {
        this.setState({
          user,
          loading: false
        })
      })
  }

  render () {
    if (this.state.loading) {
      return <LoadingPage />
    } else {
      return (
        <ApolloProvider client={client}>
          <BrowserRouter>
            ...
          <BrowserRouter />
        </ApolloProvider>  
    }
}