es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

La suscripción de rxjs se dispara pero Angular no muestra el resultado vinculado.

Obtención de plantas mediante la suscripción de rxjs a una llamada get con un resultado correcto. La suscripción se dispara (se escribe en la consola), pero Angular no muestra el resultado enlazado la primera vez, la segunda vez muestra el primer resultado, la tercera vez muestra el segundo resultado y así sucesivamente. La suscripción es un objeto de RxJS Subscription. staticDeviceService no se comparte con otros componentes. ¿Qué más no sé?

getPlants(pageNewDevice: number, pageDevice: number): void {
    if (pageDevice < 0) {
        return;
    }
    if (pageNewDevice < 0) {
        return;
    }
    this.subscription = this.staticDeviceService.getPlants(pageNewDevice, pageDevice).subscribe((resPlants) => {
        console.log("write console");
        this.devices = resPlants.deviceList;
    });
}

¡Encontré el problema! Esto sucede porque, por defecto, cuando genero el componente (¿tal vez causa de rxjs?), el change detection está configurado con ChangeDetectionStrategy.OnPush. Usé un array global inicializado con dispositivos vacíos devices = []; Cuando el observable se activa y asigna this.device = resPlants.deviceList, Angular no activa el cambio la primera vez, ¿necesito usar push? Funciona si declaro device; en lugar de device = []; Ahora, ¿cuál es la mejor práctica? ¿Usar ChangeDetectionStrategy.OnPush o es mejor usar la ChangeDetectionStrategy predeterminada de Angular con rxjs?

https://stackblitz.com/edit/angular-ivy-bz1yhj?file=src/app/app.component.ts

Tags:  , ,

Answer

  1. Avatar for davy.ai

    El problema en el código proporcionado es que cuando el observable se dispara y asigna la propiedad this.devices, el mecanismo de detección de cambios de Angular no detecta un cambio la primera vez y sólo actualiza la vista en cambios posteriores. Esto se debe a que el componente está utilizando la estrategia ChangeDetectionStrategy.OnPush.

    Una solución es volver a asignar la propiedad this.devices a una nueva referencia de array, de modo que Angular detecte un cambio y actualice la vista:

    this.subscription = this.staticDeviceService.getPlants(pageNewDevice, pageDevice).subscribe((resPlants)=>{
      console.log("escribir en la consola")
      this.devices = [...resPlants.deviceList]; // crear un nuevo array
    })
    

    Otra solución es utilizar Observable.pipe() para disparar explícitamente la detección de cambios:

    import { ChangeDetectorRef } from '@angular/core';
    import { tap } from 'rxjs/operators';
    
    constructor(private cdr: ChangeDetectorRef) {}
    
    getPlants(pageNewDevice:number, pageDevice:number):void {
      if(pageDevice < 0){
        return;
      }
      if(pageNewDevice < 0){
        return;
      }
      this.subscription = this.staticDeviceService.getPlants(pageNewDevice, pageDevice).pipe(
        tap(() => this.cdr.detectChanges()) // disparar detección de cambios
      ).subscribe((resPlants)=>{
        console.log("escribir en la consola")
        this.devices = resPlants.deviceList;
      });
    }
    

    En cuanto a si utilizar ChangeDetectionStrategy.OnPush o la estrategia predeterminada, depende de los requisitos específicos y consideraciones de rendimiento del componente. OnPush puede proporcionar beneficios de rendimiento al reducir el número de ciclos de detección de cambios, pero requiere un manejo cuidadoso de estado mutable y puede complicar la depuración. La estrategia predeterminada es más fácil de usar pero puede resultar en ciclos de detección de cambios más frecuentes.

Comments are closed.