Lazy load of page in separate module says: "Uncaught (in promise): TypeError: undefined is not a function"

Hi,

I’ve created a blank project using the blank template with ionic v2.2.3; I’m creating a practice app that has a slider menu and a lazy loading with pages in separate modules (in order to generate deep link, unless mistaken).

The stack trace isn’t very explicit - full stack trace at the bottom of this post.

Error: Uncaught (in promise): TypeError: undefined is not a function
TypeError: undefined is not a function

Here’s the problem I can’t fix… I learn using Udemy’s Max Schwarzmuller’s course and can’t find what I’ve done wrong. The course covers Ionic 2 with a few steps to mgirate to Ionic 3. I’ve searched the forum as well as stack overflow with no success. Thanks a lot in advance for your help and attention;

src/app/app.component.ts (main app component)

@Component({
  templateUrl: 'app.html'
})
export class MyApp {
  @ViewChild('nav') nav: NavController;
  homePage: any = 'JournalHome';       // REM: If I pass the page reference instead of string name, then it works.
  journalPage: any = 'JournalHome';
  constructor(platform: Platform,
              statusBar: StatusBar, splashScreen: SplashScreen,
              private menuCtrl: MenuController) {
    platform.ready().then(() => {
      statusBar.styleDefault();
      splashScreen.hide();
    });
  }
  doLoad(page: any){
    this.nav.setRoot(page);
    this.menuCtrl.close();
  }
}

As described in the “REM” in front of “homePage: any”, passing a reference to the page itself works, but not when I pass the string representation of the class name of my page.

src/app/app.module.ts (main app module)

@NgModule({
  declarations: [
    MyApp
  ],
  imports: [
    JournalHomeModule,
    BrowserModule,
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp
  ],
  providers: [
    StatusBar,
    SplashScreen,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}

Now the “separate module”:

src/pages/journal/journal.module.ts:

@NgModule({
  declarations: [
    JournalHome
  ],
  imports: [
    IonicPageModule.forChild(JournalHome)     // I understood this would make the "JournalHome" known of Ionic
  ],
  entryComponents: [
    //JournalHome        // commented out as it doesn't help. Thought it was necessary as no router or template is using this component
  ],
  exports: [
    JournalHome         // Is this doing any good? I thought it would "make the component known outside the module"
  ]
})
export class JournalHomeModule {}

And finally the page I’d like to have lazy loaded:

@IonicPage({
  // name: 'JournalHome' // commented out as it doesn't help
})
@Component({
  selector: 'page-journal-home',
  templateUrl: 'journal-home.html',
})

export class JournalHome {

  constructor() {
  }

  ionViewDidLoad() {
    console.log('JournalHome view loaded =^_^= ');
  }
}

Now the full stack trace (nothing relates to my workspace code):

core.es5.js:1084 ERROR Error: Uncaught (in promise): TypeError: undefined is not a function
TypeError: undefined is not a function
    at Array.map (native)
    at webpackAsyncContext (http://localhost:8100/build/main.js:74202:34)
    at loadAndCompile (http://localhost:8100/build/main.js:73365:36)
    at NgModuleLoader.load (http://localhost:8100/build/main.js:73330:83)
    at ModuleLoader.load (http://localhost:8100/build/main.js:55553:44)
    at DeepLinker.getNavLinkComponent (http://localhost:8100/build/main.js:20466:39)
    at DeepLinker.getComponentFromName (http://localhost:8100/build/main.js:20449:25)
    at getComponent (http://localhost:8100/build/main.js:29687:23)
    at convertToView (http://localhost:8100/build/main.js:29705:16)
    at convertToViews (http://localhost:8100/build/main.js:29724:32)
    at Array.map (native)
    at webpackAsyncContext (http://localhost:8100/build/main.js:74202:34)
    at loadAndCompile (http://localhost:8100/build/main.js:73365:36)
    at NgModuleLoader.load (http://localhost:8100/build/main.js:73330:83)
    at ModuleLoader.load (http://localhost:8100/build/main.js:55553:44)
    at DeepLinker.getNavLinkComponent (http://localhost:8100/build/main.js:20466:39)
    at DeepLinker.getComponentFromName (http://localhost:8100/build/main.js:20449:25)
    at getComponent (http://localhost:8100/build/main.js:29687:23)
    at convertToView (http://localhost:8100/build/main.js:29705:16)
    at convertToViews (http://localhost:8100/build/main.js:29724:32)
    at c (http://localhost:8100/build/polyfills.js:3:13535)
    at Object.reject (http://localhost:8100/build/polyfills.js:3:12891)
    at NavControllerBase._fireError (http://localhost:8100/build/main.js:44060:16)
    at NavControllerBase._failed (http://localhost:8100/build/main.js:44048:14)
    at http://localhost:8100/build/main.js:44103:59
    at t.invoke (http://localhost:8100/build/polyfills.js:3:9283)
    at Object.onInvoke (http://localhost:8100/build/main.js:4427:37)
    at t.invoke (http://localhost:8100/build/polyfills.js:3:9223)
    at r.run (http://localhost:8100/build/polyfills.js:3:4452)
    at http://localhost:8100/build/polyfills.js:3:14076

Well, well, I’ve re-created my project in spite of a better approach. I don’t run in this weird error. Lazy loading just works now.

Note to self with Ionic3 in mind:

  • app.module must not import the lazy loaded page module
  • app.component must not import the lazy loaded page, just refer to it by string
  • lazy loaded page module needs not to reference the page in entryComponents nor does it need to export it

I’ll update further if come across what I’ve done wrong in the previous attempt.

3 Likes

Just had to do this for an old project. Thanks for the post, this is the most relevant one I have found. The problem for me was indeed a double use of the HomePage import - both directly calling it and using lazy loading. I had to pick one or the other, then webpack didn’t have any issues.

The key is for the rootPage ( not necessarily other pages )

  1. that if you are using lazy loading, you only reference it by string and
  2. that you remove HomePage or HomePageModule from app.module.ts imports.
  3. run npm run clean – this part is important
  4. now npm start will work.

This wasn’t an issue until app-scripts 3.2.0 - but I needed 3.2.4 to support Node 14. Thanks derceto!