问题
am trying to learn angular by following the official tutorial (https://angular.io/tutorial/) but when following steps for hero component and hero detail component, it raises an error "RangeError: Maximum call stack size exceeded" .
the hero.component.html and detail code is as under:
<ul class="heroes">
<li *ngFor="let hero of heroes" (click)="onSelect(hero)" [class.selected]="hero === selectedHero">
<span class="badge">{{hero.id}}</span> {{hero.name}}
</li>
</ul>
<!--
<app-hero-detail [hero]="selectedHero"></app-hero-detail> -->
<app-heroes></app-heroes>
for detail:
<div *ngIf="hero">
<h2>{{hero.name}} Details</h2>
<div><span>id: </span>{{hero.id}}</div>
<div>
<label>name:
<input [(ngModel)]="hero.name" placeholder="name"/>
</label>
</div>
</div>
<app-hero-detail [hero]="selectedHero"></app-hero-detail>
hero component
import { Component, OnInit } from '@angular/core';
import { Hero } from '../hero';
import { HEROES } from '../mock-heroes';
import { HeroService } from '../hero.service';
@Component({
selector: 'app-heroes',
templateUrl: './heroes.component.html',
styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
heroes: Hero[];
selectedHero: Hero;
constructor(private heroService: HeroService) { }
ngOnInit() {
this.getHeroes();
}
getHeroes(): void {
this.heroes = this.heroService.getHeroes();
}
onSelect(hero: Hero): void {
this.selectedHero = hero;
}
}
hero.detail component
import { Component, OnInit, Input } from '@angular/core';
import { Hero } from '../hero';
@Component({
selector: 'app-hero-detail',
templateUrl: './hero-detail.component.html',
styleUrls: ['./hero-detail.component.css']
})
export class HeroDetailComponent implements OnInit {
@Input() hero: Hero;
constructor() { }
ngOnInit() {
}
}
one thing to mention is that when <app-heroes></app-heroes>
is commented, the list page is loaded without error
any help appreciated
回答1:
1.This error occur when there is an infinite loop. As you have mentioned that the page loads when app-heroes is commented, this might be used as selector-name for more than one component which is not allowed. This can cause an infinite loop and fail to load components.
- Try making below edits,
hero.component.html
<ul class="heroes">
<li *ngFor="let hero of heroes" (click)="onSelect(hero)" [class.selected]="hero === selectedHero">
<span class="badge">{{hero.id}}</span> {{hero.name}}
</li>
</ul>
<app-hero-detail [hero]="selectedhero"></app-hero-detail>
hero.detail.component.html
<div *ngIf="hero">
<h2>{{hero.name}} Details</h2>
<div><span>id: </span>{{hero.id}}</div>
<div>
<label>name:
<input [(ngModel)]="hero.name" placeholder="name"/>
</label>
</div>
</div>
Hope this helps.
回答2:
In your example you render component inside yourself, so you never finish this operation and all time render another child component (if second part of block is
Update - more details:
If you write app with components, all components are hierarchical, so you can include the same component inside yourself only if you are sure, that this is limited amount of loop inside. In your code example you has unlimited nested components, because child component generate next child component inside yourself body. In result your browser display error: RangeError: Maximum call stack size exceeded
hero.component.html
<ul class="heroes">
<li *ngFor="let hero of heroes" (click)="onSelect(hero)" [class.selected]="hero === selectedHero">
<span class="badge">{{hero.id}}</span> {{hero.name}}
</li>
</ul>
<!--
<app-hero-detail [hero]="selectedHero"></app-hero-detail> -->
<app-heroes></app-heroes>
app-hero-details.component.html
<div *ngIf="hero">
<h2>{{hero.name}} Details</h2>
<div><span>id: </span>{{hero.id}}</div>
<div>
<label>name:
<input [(ngModel)]="hero.name" placeholder="name"/>
</label>
</div>
</div>
// you should comment line below
// <app-hero-detail [hero]="selectedHero"></app-hero-detail>
回答3:
I will add an answer that describes a different cause for this error when upgrading to angular 8 an existing aplication and using new routing features.
In my case, I added to each lazy loaded route the data
object with preload
set to true || false
using the new syntax:
{
path: '',
loadChildren: () => import('./views/home/home.module').then(mod => mod.HomeModule),
data: { preload: true }
},
However it took me a while to realize that I had left the preloadingStrategy
set to PreloadAllModules
in my RouterModule
forRoot declaration:
@NgModule({
imports: [RouterModule.forRoot(
routes,
{
preloadingStrategy: PreloadAllModules, <-- This is the cause
})],
...
Removing preloadingStrategy from the module forRoot declaration and relying on the route data preload definitio fixes the issue.
回答4:
You have the <app-hero-detail>
displayed inside the details HTML.
<app-hero-detail [hero]="selectedHero"></app-hero-detail>
Please try removing this. A similar line is commented in the hero.component.html
, you can uncomment that.
回答5:
A different cause for this error when upgrading to angular 8 an existing application and using new routing features in separate file.
In my case not importing the featureRouterModule
to its particular featureModule.ts
cause maximum stack exceed error.Since angular can't find its particular router file registered
回答6:
I was able to reproduce this error message when I created a module and I forget to add the RoutingModule.
@NgModule({
declarations: [
SuccessComponent,
CheckoutComponent
],
imports: [
ShareModule,
PaymentRoutingModule // Forget to add it.
]
})
export class PaymentModule { }
I have no idea why I got this error, but maybe another person can make the same mistake.
回答7:
I was dealing with this error when my intellisense accidentally added the module name (instead of a specific component name) to the exports for the module:
@NgModule({
declarations: [
FooComponent,
// ...
],
imports: [CommonModule],
exports: [
FooModule, // <== should be 'FooComponent'
// ...
],
})
export class FooModule {}
It definitely would be nice if the error was a little more descriptive though, as this tool me some time
回答8:
This error occurred when I used a circular module import mistakenly on Angular 9.
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
@NgModule({
imports: [
CommonModule,
ModuleTwo
],
})
export class ModuleOne {
}
and
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
@NgModule({
imports: [
CommonModule,
ModuleOne
],
})
export class ModuleTwo {
}
回答9:
I named two modules similarly and didn't pay attention to which I imported. If you import a module inside itself it will cause circular import till maximum call stack is reached.
回答10:
Possible cases for this error which I found:
- 2 or more modules with the same name
- Wrong imports in your
app.module.ts
file - Problem with compilation
Solution that you can try:
- for point 1, change the names and make them unique
- for point 2, make sure all imports are intended as per your use case for a module, do check for inter-dependency between modules
- for point 3, rare but happens if browser doesn't have enough memory to process, so try to restart your code editor, browser or your PC.
回答11:
This, in my case was an issue caused by recursion. There wasn't a condition to break out of the recursive function, but lucky enough I managed to pick that up.
来源:https://stackoverflow.com/questions/53756451/angular-7-error-rangeerror-maximum-call-stack-size-exceeded