12

I'm using apollo client for graphql. I set up the client in AppApolloModule that I'm importing in AppModule. I'm making a query in a service which is also imported right in the AppModule. Although the service runs before the AppApolloModule runs and hence apollo is not initialized when the query is made and I get this error

Error: Client has not been defined yet

AppApolloModule

imports ....

export class AppApolloModule {

    constructor(
        apollo: Apollo,
        httpLink: HttpLink,
        private userService: UserService
    ) {
        console.log("apollo module")
        apollo.create({
            link: httpLink.create({ uri: `${environment.apiBase}/graphql?${this.myService.token}`}),
            cache: new InMemoryCache()
        })
    }

}

App Module

import { AppApolloModule } from './app.apollo.module';
import { MyService } from './services/my.service';

export class AppModule {
      constructor() {
        console.log("app module")
      }
}

I don't get the two consoles app module and apollo module, since the service runs first, it doesn't find any initialized apollo app and thus breaks the code.

How can I make apollo run before the service or any services for that matter in an efficient and standard way?

8
  • Have you tried using app lifecycle OnInit ? try implementing the OnInit interface and bring your code into the ngOnInit method Commented Mar 13, 2018 at 13:44
  • Maybe have a look at APP_INITIALIZER token
    – David
    Commented Mar 13, 2018 at 13:47
  • @e.m.b services don't have ngOnInit Commented Mar 13, 2018 at 14:04
  • I meant move the code in the modules constructor to the ngOnInit in the modules not the services Commented Mar 13, 2018 at 15:12
  • @e.m.b that won't help either, as contructor function runs first, putting it on ngOnIt will make them load even after more time Commented Mar 13, 2018 at 16:44

5 Answers 5

9

This will solve the issue nicely:

import {NgModule} from '@angular/core';
import {HttpClientModule} from '@angular/common/http';
import {ApolloModule, APOLLO_OPTIONS} from 'apollo-angular';
import {HttpLink, HttpLinkModule} from 'apollo-angular-link-http';
import {InMemoryCache} from 'apollo-cache-inmemory';

export function createApollo(httpLink: HttpLink) {
  return {
    link: httpLink.create({uri: 'https://api.example.com/graphql'}),
    cache: new InMemoryCache(),
  };
}

@NgModule({
  imports: [HttpClientModule, ApolloModule, HttpLinkModule],
  providers: [
    {
      provide: APOLLO_OPTIONS,
      useFactory: createApollo,
      deps: [HttpLink],
    },
  ],
})
class AppModule {}
5
  • Yay! Much better like this. Too bad the Apollo docs don't put this as the first example. Commented Jul 17, 2018 at 10:25
  • 1
    Did you just move the instantiation of Apollo inside AppModule? Commented Oct 13, 2019 at 1:27
  • 3
    After upgrading to Apollo v3 - this approach is giving me the issue again "Client has not been defined yet"
    – DauleDK
    Commented Sep 8, 2020 at 13:02
  • @DauleDK how did you fixed it ? Commented Feb 25, 2021 at 17:10
  • We switched the stack to Svelte/Sapper - we never managed to fix the issue in our team.
    – DauleDK
    Commented Feb 25, 2021 at 19:13
1

I have the same issue an the docs from Apollo helped me. Go to 'https://www.apollographql.com/docs/angular/basics/setup/' or copy this:

import { HttpClientModule } from "@angular/common/http";
import { ApolloModule, APOLLO_OPTIONS } from "apollo-angular";
import { HttpLinkModule, HttpLink } from "apollo-angular-link-http";
import { InMemoryCache } from "apollo-cache-inmemory";

@NgModule({
  imports: [
    BrowserModule,
    HttpClientModule,
    ApolloModule,
    HttpLinkModule
  ],
  providers: [{
    provide: APOLLO_OPTIONS,
    useFactory: (httpLink: HttpLink) => {
      return {
        cache: new InMemoryCache(),
        link: httpLink.create({
          uri: "https://o5x5jzoo7z.sse.codesandbox.io/graphql"
        })
      }
    },
    deps: [HttpLink]
  }],
})
export class AppModule {}
0

The answer by @wendellmva didn't work for me. What did work was the solution suggested in this repo:

https://github.com/patricknazar/angular-lazy-loading-apollo-client

which is basically to put Apollo initialization in a separate, shared module, and include it in your main app module with forRoot().

4
  • 6
    This link is no longer available.
    – kozan
    Commented Jun 19, 2020 at 17:45
  • Could you update the link to the repository please?
    – jowey
    Commented Feb 15, 2021 at 10:36
  • 1
    @jowey it appears that the owner removed it and unfortunately I didn't think of cloning it at the time. Our setup is a bit more complex now, so I cannot post it here. Perhaps the official documentation has been updated, as raffaval writes below? Commented Feb 15, 2021 at 17:09
  • Try this: apollo-angular.com/docs/get-started Commented Feb 15, 2021 at 17:11
0

What worked for me was deleting the .angular folder and serving the application again.

0

Here is how it worked for me with angular +16/17:

app.config.ts

import { ApplicationConfig, importProvidersFrom } from '@angular/core';
import { provideHttpClient } from '@angular/common/http';
import {
  provideRouter,
  withComponentInputBinding,
  withEnabledBlockingInitialNavigation,
  withViewTransitions,
} from '@angular/router';
import { appRoutes } from './app.routes';
import { provideAnimations } from '@angular/platform-browser/animations';
import {
  ApolloClientOptions,
  ApolloLink,
  GraphQLRequest,
  InMemoryCache,
} from '@apollo/client/core';
import { APOLLO_OPTIONS, ApolloModule } from 'apollo-angular';
import { HttpLink } from 'apollo-angular/http';
import { setContext } from '@apollo/client/link/context';
import { SECRET, URI, PROPERTY } from './uri-info';

export function createApollo(httpLink: HttpLink): ApolloClientOptions<any> {
  const headers = setContext((operation: GraphQLRequest, context) => ({
    headers: {
      [PROPERTY]: SECRET,
    },
  }));
  return {
    link: ApolloLink.from([headers, httpLink.create({ uri: URI })]),
    cache: new InMemoryCache(),
  };
}

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(
      appRoutes,
      withEnabledBlockingInitialNavigation(),
      withComponentInputBinding(),
      withViewTransitions(),
    ),
    provideHttpClient(),
    provideAnimations(),
    importProvidersFrom(ApolloModule),
    {
      provide: APOLLO_OPTIONS,
      useFactory: createApollo,
      deps: [HttpLink],
    },
  ],
};

init-graphQl.component.ts

import { Apollo, gql } from 'apollo-angular';
import { Component, OnInit, inject } from '@angular/core';

@Component({
  standalone: true,
  selector: 'test-init-graphql',
  template: `Console log is here`,
})
export class InitGraphQlComponent implements OnInit {
  #apollo = inject(Apollo);

  ngOnInit(): void {
    this.#apollo
      .watchQuery({
        query: gql`
          {
            Entity {
              firstProperty
              secondProperty
            }
          }
        `,
      })
      .valueChanges.subscribe((result: any) => {
        console.log(result);
      });
  }
 }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.