html - Angular ngFor körs i en oändlig loop när en array visas


Jag försöker för närvarande att skapa en Logbox för min webbapp. Den får en Array med loggar och ska visa dem rad för rad i en div. Jag använder ngFor och loopar igenom min Array med loggar och sedan visar dem.

Mitt problem nu är att loggarna visas oändligt många gånger, inte bara 5 gånger (5 arrayposter i listan) som det borde.

Har någon en ledtråd om vad jag saknar?

logs.component.html

<div class="logContent">
    <div class="row">
      <div class="col-12" *ngFor="let log of this.logService.getLogs()">
        <app-singlelog [when]="log.when" [type]="log.type" [data]="log.data"></app-singlelog>
      </div>
    </div>
  </div>

log.service.ts

export class LogService {
  private logArray = [];
  /* private logObject = {} as Log; */

  constructor(private httpservice: HttpserviceService) { 
    
  }

  public getLogs(): Array<Log> {
    this.httpservice.getLogs().subscribe(data => {
      data.forEach(index => {
        let logObject = {} as Log;
        logObject.when = index.when;
        logObject.type = index.type;
        logObject.data = index.data;
        this.logArray.push(logObject);
      })
    }
    )
    return this.logArray;
  }
}

Tack :)

Svar #1

Använd inte funktionsanrop från HTML-mallen för att visa data.
Anropa istället getLogs()-funktionen från Angulars ngOnInit()-funktion och lagra svaret i en variabel. Loopa sedan på den variabeln:

export class LogService implements OnInit {
// ...

logs = [];

ngOnInit() {
   this.getLogs();
}

getLogs(): Array<Log> {
    this.httpservice.getLogs().subscribe(data => {
      data.forEach(index => {
        let logObject = {} as Log;
        logObject.when = index.when;
        logObject.type = index.type;
        logObject.data = index.data;
        this.logArray.push(logObject);
      });
      // assign the variable here:
      this.logs = data;

    });
}

I mallen:

 <div class="col-12" *ngFor="let log of logs">
   <app-singlelog [when]="log.when" [type]="log.type" [data]="log.data"></app-singlelog>
</div>

Anledningen bakom detta är det faktum att Angular anropar din getLogs-funktion vid varje sidrenderingscykel. Men du bör bara anropa HTTP-förfrågan en gång, när du initierar komponenten.

Glöm inte att avanmäla dig från din Observable. ;) - korrigerad från kommentaren nedan.

Svar #2

Du kan också använda den reaktiva metoden och göra följande:

Definiera den observerbara en gång i din komponent:

logs$ = this.httpservice
    .getLogs()
    .pipe(
      shareReplay(),
      map((data) => data.map(({ when, type, data }) => ({ when, type, data })))
    );

Inkludera följande i din komponent-HTML:

<div class="col-12" *ngFor="let log of logs$ | async">
   <app-singlelog [when]="log.when" [type]="log.type" [data]="log.data"></app-singlelog>
</div>

Relaterade artiklar