Search code examples
reactjsreact-hooksgraphqlapollo

How do I run an Apollo graphQL query before the App component is first rendered? (_and depends on it_)


I need to call an Apollo query and the App component depends on its result, so how can I accomplish that?
I specifically want to redirect the user to a page based on their privileges.
I can't figure out how or where to call the query.

File App.tsx

    // ...
    client = new ApolloClient({
      cache: new InMemoryCache(),
      link: ApolloLink.from([authMiddleware, errorlink, httpLink]),
      credentials: 'include',
    });

    export const App: FC = () => {
      // This doesn't work, I guess because it's not "inside" the ApolloProvider
      const { loading, error, data: { user } } = useQuery<{ user: User }>(whoAmIQuery);

      // this doesn't work either because I can't define the React.FC as an async function
      const result = await client.query({query: whoAmIQuery});

      return (
        <div className="app">
          <CookiesProvider>
            <Router history={browserHistory}>
              <ApolloProvider client={client}>
                <Suspense fallback={<div />}>
                  <Switch>
                    <Route path="/login" exact>
                      <LoginPage />
                    </Route>
        <!-- ... -->

Solution

  • Make use of loading state provided by useQuery. Wrap your App.tsx in another component or file like bootstrap.tsx

    bootstrap.tsx

    export const RenderApp: FC = () => {
      //Initialize your client here...
    
      return (
         <ApolloProvider client={client}>
             <App/>
         </ApolloProvider>
      );
    

    App.tsx

       export const App: FC = () => {
          // This doesn't work, I guess, because it's not "inside" the ApolloProvider
          const { loading, error, data: { user } } = useQuery<{ user: User }>(whoAmIQuery);
    
          // this doesn't work either because I can't define the React.FC as an async function
          const result = await client.query({query: whoAmIQuery});
    
      return (
        <>
          {loading && <div>Loading state</div>}
          {!loading && data && (
            <div>Your Code</div>
          )}
          {!loading && error && <div>Error state</div>}
        </>
      );