bestsource

왜 ngOnInit가 두 번 호출됩니까?

bestsource 2023. 8. 7. 22:46
반응형

왜 ngOnInit가 두 번 호출됩니까?

새로운성구요만소합니다고들려를▁new,▁component▁create다합▁to▁i니를 만들려고 합니다.ResultComponent그러나 그것은ngOnInit()메소드가 두 번 호출되고 있는데 왜 이런 일이 일어나는지 모르겠어요. 에서코드,ResultComponent@Input 구성 요소에서mcq-component.

코드는 다음과 같습니다.

상위 구성요소(MCQ 구성요소)

import { Component, OnInit } from '@angular/core';

@Component({
    selector: 'mcq-component',
    template: `
        <div *ngIf = 'isQuestionView'>
            .....
        </div>
        <result-comp *ngIf = '!isQuestionView' [answers] = 'ansArray'><result-comp>
    `,
    styles: [
        `
            ....
        `
    ],
    providers: [AppService],
    directives: [SelectableDirective, ResultComponent]
})
export class MCQComponent implements OnInit{
      private ansArray:Array<any> = [];
    ....
    constructor(private appService: AppService){}
    ....
}

하위 구성 요소(result-comp)

import { Component, OnInit, Input } from '@angular/core';

@Component({
    selector:'result-comp',
    template: `
        <h2>Result page:</h2>

    `
})
export class ResultComponent implements OnInit{
    @Input('answers') ans:Array<any>;

    ngOnInit(){
        console.log('Ans array: '+this.ans);
    }
}

시, 행실시시,console.log는 두, 첫 배열을 두 는 는 두 번 표 됩 니 시 다 첫 른 지 만 하 을 표 니 다 합 제 번 는 공 째 두 시 배 열 올 는 바 째 번 니 ▁is 다 ▁showing 합 ▁up ▁two는 ▁but , 제공는째번▁times▁the첫▁the두▁gives▁the두다니▁array▁correct번▁it지째됩만undefined요: 왜 그알아수낼없을다니었: 왜가는나습것.ngOnInitResultComponent두 번이나 전화를 받았습니까?

두 번 호출되는 이유

현재 구성 요소의 콘텐츠/뷰 자식 변경을 감지하는 동안 오류가 발생하면 ngOnInit가 두 번 호출됩니다(DynamicChangeDetector 참조).이로 인해 원래 오류를 숨기는 확인할 메일 오류가 발생할 수 있습니다.

이 정보는 이 Github 문제에서 가져옵니다.


따라서 당신의 실수는 이 구성 요소와 관련된 코드의 다른 부분에서 발생한 것으로 보입니다.

이것은 HTML 구성 요소의 결함 때문에 저에게 일어난 일입니다.호스트 구성 요소에서 선택 도구 태그를 닫는 것을 잊었습니다.그래서 저는 이것을 가지고 있었습니다.<search><search><search></search>구문 오류를 기록합니다.

따라서 @dylan 답변과 관련하여 구성 요소 html 구조와 상위 구조를 확인하십시오.

제 경우 문제는 하위 구성요소를 부트스트랩하는 방식이었습니다.@NgModule decorator의 메타데이터 개체에서 bootstap 속성의 'child component'와 함께 'parent component'를 전달하고 있었습니다.부트스탭 속성에서 자식 구성 요소를 전달하는 것은 자식 구성 요소 속성을 재설정하고 OnInit()를 두 번 실행하는 이었습니다.

    @NgModule({
        imports: [ BrowserModule,FormsModule ], // to use two-way data binding ‘FormsModule’
        declarations: [ parentComponent,Child1,Child2], //all components
        //bootstrap: [parentComponent,Child1,Child2] // will lead to errors in binding Inputs in Child components
        bootstrap: [parentComponent] //use parent components only
    })

을 사용한 platformBrowserDynamic().bootstrapModule(AppModule);app.try.app.app.ts.ts에서 댓글을 달 수 있습니다.저도 같은 문제가 있었습니다.이게 도움이 될 것 같습니다.

는 설하기때이발수있생습다니할문가제문을 할 수 .AppComponent로서.

RouterModule.forRoot([
    { path: '', component: AppComponent }  // remove it
])

참조: AppComponent으로 에서기호다니출에서 됩니다.angular따라서 아래와 같이 다시 호출할 필요가 없습니다.

@NgModule({
  declarations: [
    AppComponent,
  ],
  bootstrap: [AppComponent] // bootstraping here by default
})
export class AppModule { }

누군가 여기로 올 경우를 대비해서 이걸 여기에 두는 것.브라우저의 기본 버튼 유형이 "제출"인 경우 NgOnInit를 두 번 호출할 수도 있습니다. 예를 들어, 아래와 같은 것이 있으면 크롬에서 NgOnInit가 두 번 호출됩니다.

<button class="btn btn-primary" (click)="navigateToNextComponent()">

수정하려면 유형을 설정합니다.

<button class="btn btn-primary" type="button" (click)="navigateToNextComponent()">

ngOnInit()모든 디렉티브가 인스턴스화된 후 한 번만 후크가 실행됩니다.▁inside▁you▁ngOnInit()구독을 취소하지 않고 구독한 데이터가 변경되면 다시 실행됩니다.

다음 Stackblitz 예제에서는 내부에 구독이 있습니다.ngOnInit()그리고 결과를 위로합니다.한 번 로드하면 데이터가 변경되고 다시 로드되기 때문에 콘솔이 두 번 작동합니다.

스택블리츠

이 문제는 템플릿 오류가 있을 때마다 발생합니다.

저의 경우 잘못된 템플릿 참조를 사용하여 문제를 해결했습니다.

제 경우, 빌드에서 각 파일 main-es5.js 및 main-es2015.js의 복제를 생성하여 *-es5.js의 복제를 모두 삭제하고 작동했습니다.

그것도 당신의 경우라면, 중복을 삭제하지 말고 그 속성을 추가하세요.

<script src="elements-es5.js" nomodule defer>
<script src="elements-es2015.js" type="module">

제가 이름을 밝히지 않은 상태에서 이런 일이 벌어졌습니다.<router-outlet>*ngFor루프의 각 반복에 대해 로드되었습니다.

은 각 한 이름을 와 an an an an an an an an an an an an an an an an an an an an an an an an an an an an an DOM an an an an an an an an an an an an an an an an an an an an an an an an an an an *ngIf).

Route:에서 동일한 구성 요소를 두 번 등록했기 때문에 이 문제가 발생했습니다.

{
        path: 'meal-services',
        children: [
          {
            path: '',
            component: InitTwiceComponent,
            canActivate: [AppVendorOpsGuard],
            data: { roleWhitelist: [UserRoles.Manage] }
          },
          {
            path: ':itemID',
            component: InitTwiceComponent,
            canActivate: [AppVendorOpsGuard],
            data: { roleWhitelist: [UserRoles.Manage] }
          }]
      },
}

이 문제는 다음과 같은 라우터 출구가 여러 개 있는 경우에 발생할 수 있습니다.

<ng-container *ngIf="condition">
  <div class="something">
    <router-outlet></router-outlet>
  </div>
</ng-container>
<ng-container *ngIf="!condition">
  <div class="something-else">
    <router-outlet></router-outlet>
  </div>
</ng-container>

이렇게 하면 생성자를 두 번 호출할 수도 있습니다.가 두 번가 두 번 인데, 이는 가 자가두두번사구증생며요, 구내발다니합생있정때 안에 때 정확히 입니다.*ngIf로 전환됩니다.

이를 디버깅하는 유용한 방법은 다음과 같이 rnd라는 클래스 변수를 만드는 것입니다.

rnd = Math.random()

console.log를 생성자 및 ngOnInit 내부에 저장합니다.값이 변경되면 두 번째 호출 시 구성 요소의 새 인스턴스가 있고 동일한 인스턴스가 두 번 호출되지 않음을 알 수 있습니다.이렇게 해도 문제가 해결되지는 않지만 문제를 나타낼 수 있습니다.

이 경우 Component가 OnChanges와 OnInit모두 구현할 때 발생합니다.이 클래스 중 하나를 제거합니다.또한 ngAfterView를 사용할 수 있습니다.init 메서드는 뷰가 초기화된 후 트리거되므로 한 번 호출됩니다.

저도 비슷한 문제가 있었습니다. 구성 요소를 요청한 다음 라우터 콘센트를 통해 동일한 구성 요소를 참조하고 있었습니다.

<layout>
  <router-outlet></router-outlet>
</layout>

그리고 출구 경로도 레이아웃을 가리키고 있었습니다.

이것은 저에게 어린이 구성요소에서 일어난 일입니다.하위 구성 요소는 *ngIf를 사용하여 특정 조건이 충족될 때 표시합니다.나의 해결책은 ngIf를 ngClass로 대체하는 입니다.

HTML에서:

<component [ngClass]="isLoading?'hide':'show'>"

CSS:

.show{ display: block; }

.hide{ display: none; }

제가 2021년에 이 문제를 우연히 발견했을 때, 저는 최근에 오래된 ng4에서 더 최근의 ng10으로 이주했습니다.그러나 앱이 index.jsp를 통해 모노리식 Java 백엔드에 통합되어 있어 제대로 마이그레이션하지 않았습니다.
유사한 위치에 있는 경우 다음을 확인합니다.<script>는 "". *-es2015.js 파일이어야 .type="module"에는 *-es5.js에는 *-es5.js라는 이름이 있어야 .nomodule defer집합, 즉:

<script src=".../main-es5.js" nomodule defer></script>
<script src=".../main-es2015.js" type="module"></script>

저의 경우 ngOnInit 내에 있는 모든 구독을 취소하지 않았습니다.방금 ngOnDestroy의 모든 구독에서 구독을 취소하여 문제가 해결되었습니다.

나의 경우 app.component.html에서 이것을 일으킨 것은 html 오류였습니다.

<icpm-la-test><icpm-la-test>

대신에

<icpm-la-test></icpm-la-test>

닫는 태그 대신 여는 태그가 두 개 있었고, 콘솔에 오류가 없었고 ngOnInit가 두 번 호출되어 구독과 관련하여 여러 API 호출이 발생한 것을 제외하고는 기능이 잘 작동했습니다.

실수로 구성 요소를 두 번 시작한 것일 수 있습니다.이는 몇 가지 이유 때문일 수 있습니다.

  1. 을 가져왔습니다.AppRoutingModule둘 이상의 모듈로.앱 전체에서 검색하고 해당 앱에만 포함되도록 합니다.AppModule.

  2. 을 가져왔습니다.AppModule다른 모듈로 이동합니다. 당신의 을 할 수 .AppRoutingModule제1항에 따라

  3. 개 의 두개이있다니가 있습니다.<router-outlet>당신의 마크업에서. 개의 경로가 둘 가 필요하기 스러울 수 .<router-outlet>각해야 합니다.<router-outlet>때때로 실제 출력이 무엇인지 확인하기 위해 부모 내부에 중첩된 각 구성 요소를 복사하는 것이 더 쉽습니다.그러면 당신은 당신이 여분을 갖게 되었는지 볼 수 있습니다.<router-outlet>

  4. 래퍼 구성 요소는 AppRoutingModule과 하위 구성 요소 내부에 지정되어 있습니다.종종 머리글, 바닥글, 메뉴 등과 같은 표준 레이아웃을 처리하는 래퍼 구성요소가 있습니다.그러면 내 아이의 모든 경로가 내 안에 설정될 때 이 안에 있을 것입니다.AppRoutingModule 이 요소를 다른 요소 할 수 이미 할 수 있습니다.AppRoutingModule이것은 추가로 이어질 것입니다.<router-outlet>.

XComponent를 배치했습니다.

부트스트랩: [AppComponent, XComponent]

app.s.ts.에

XComponent ngOnInit를 제거한 후 한 번만 트리거되었습니다.

앵커 태그에 href="#" 속성이 있어서 이런 일이 발생했습니다. 앵커 태그에 사용하지 마십시오.아래와 같은 각도 코드에 따라 routerLink를 사용하고 appComponent.ts에 ngInit(0 메소드)가 있는 것을 피하려고 하면 이 문제가 해결됩니다.

<a  class="nav-link" [routerLink]="['/login']"> Sign In. </a>

은 해책다같습다니음과제은을 사용하는 것이었습니다.ngIf정의되지 않은 입력을 방지하기 위한 구성 요소의 경우 다음과 같습니다.

<result-comp *ngIf="answers" [answers]="answers"></result-comp>

저의 경우, Login 페이지가 Sign Out 버튼을 누른 후 두 번 호출되는 것이 문제였습니다.사인 아웃 버튼의 구문이 잘못되었습니다.문제를 일으키는 코드는 다음과 같습니다.

<a routerLink="/login">
  <i class="fa fa-sign-out" (click)="logout()"></i>
</a>

아이콘 태그에서 클릭 이벤트를 제거하고 링크 태그에 넣음으로써 문제가 해결되었습니다.

<a routerLink="/login" (click)="logout()">
  <i class="fa fa-sign-out"></i>
</a>

main.ts 파일을 확인합니다.기본적으로 Angular 앱에는 플랫폼 BrowserDynamic()에 대한 이 두 개의 별도 참조가 있다고 생각합니다.저는 두 번째 것에 대해 의견을 제시했고 효과가 있었습니다.

const platform = platformBrowserDynamic(); 플랫폼.부트스트랩 모듈(앱 모듈);

//platformBrowserDynamic().bootstrapModule(AppModule) // .module(err = > console.error(err));

언급URL : https://stackoverflow.com/questions/38787795/why-is-ngoninit-called-twice

반응형