El hook ngOnDestroy() & SetInput tiene una importancia clave para el cuidado de nuestra aplicación. Su funcionalidad más importante es la liberación de espacio en memoria de variables para que no se acumule. Si esto llegara a suceder en tu aplicación, la misma podría volverse lenta y tosca a medida que toda la memoria del navegador es ocupada.
Liberando espacio de memoria
Todo el ecosistema Angular está basado en observables para el manejo asincrónico.
Cada vez que utilices un subscribe() para escuchar la respuesta de algún evento asincrónico (por ejemplo, el llamado a una API), es relevante realizar el respectivo unsubscribe() para liberar ese espacio en memoria.
RxJS
RxJS (Reactive Extensions Library for JavaScript) es una popular librería de Javascript para el manejo de observables. Si trabajas con Angular esta librería será tu mejor amiga.
Observa el siguiente ejemplo donde primero se importa Subscription desde rxjs para tipar la variable suscription. Guardamos el observable para posteriormente darlo de baja. También importamos interval que devuelve el observable y genera un contador que emite una pulsación, en este ejemplo, cada 1000 milisegundos.
En el ngOnInit(), se está suscribiendo a la propiedad this.count para imprimir por consola, cada 1000 milisegundos, el contador. Podrás observar en la consola del navegador el contador corriendo:
Si nuestro código acabara aquí, cuando el componente es destruido, el contador continuaría ocupando memoria que ya no debería ser utilizada.
Para solucionar esto, guardamos en this.suscription el observable del contador y en ngOnDestroy() y llamamos al método .unsubscribe() para detener el contador.
Contribución creada con los aportes de Kevin Fiorentino.
Manejo de eventos y limpieza en Angular con ngOnDestroy y setters
explica medio confuso, toma como ejemplo img pero en realidad son strings y se siente que no hay estructura igual podria dar un ejemplo mas practico para usar el ngOnDestroy y ngOnChanges luego el ingles... no es todo malo pero todos los cursos de angular los da el y a veces cansa escuchar a la misma persona (pasaria con cualquier profesor jaja)
un ejemplo más práctico podría ser :
OnInit crea y se suscribe a un obsevable que escucha cambios en un registro de la base de datos.
OnDestroy cancela la suscripción a ese observable para que siga llamando a la bd infinitamente.
Ese es un uso muy común pero para alguien que está iniciando comprender sobre observables es complejo.
A mi me paso lo mismo con el curso de react jajjaja
Son dos clases en una esta.
Primero hay que entender el uso de ngOnDestroy() para liberar espacio de memoria cuando un componente se destruye desuscribiendo observables, por ejemplo.
Otra cosa es el SetInput para estar escuchando cambios en un @Input(). Es muy útil realmente, yo lo he utilizado mucho.
Es avanzado, mastiquenlo despacio y lean la documentación oficial para entenderlo.
Hola, de casualidad tienes el link a la documentación oficial de esto? Realmente no lo conseguí.
Hola @willdev, te dejo una página de la web oficial de Angular, te comparto también un post de Stack Overflow.
Espero sea de ayuda, saludos!
En el min 8:24 hace un cambio repentino de tema, bien podrían ser 2 videos uno para ngDestroy y otro para SetInput
El profe es muy bueno! Pero primera vez en sus cursos que me pierdo, podrían haber dividido estos dos temas en dos videos.
Si, creo que tienes razón al pasar a setInput creí que estaba dentro del mismo tema y era otra opción para liberar memoría... me costo un poco darme cuenta que eran dos cosas diferentes. Pero aún así muy bueno los dos temas, muy útil.
A mi también como ahora me tcoa estar repitiendo!
Podemos utilizar este método para convertir en observable a un input, de esa manera al momento de un cambio, podemos decidir que hacer con el y aplicar código de ser necesario
Lo utilizamos de la siguiente manera:
@Input()setnombreInput(valorInput: string){this.variableComponente= valorInput
//aqui va el codigo que se ejecutara al cambiar el valor del input}
Más que un observable pensaría que es un Handler.
Un observable conlleva el uso del patrón suscriber - publisher.
Saludos y Éxitos
Window.clearInterval(this.counterFc); no es lo mismo que window.clearInterval(this.counterFc);
La mayuscula inicial no permite correrlo de forma correcta.
que forma mas curiosa de realizar un watcher con Angular
Todo el ecosistema Angular está basado en observables para el manejo asincrónico.
En Angular, puedes liberar espacio de memoria al destruir un componente o directiva que ya no se está utilizando. Cuando Angular destruye un componente o directiva, libera automáticamente todos los recursos que se asignaron a ella.
Sin embargo, en algunos casos, es posible que debas realizar tareas adicionales para liberar espacio de memoria. Por ejemplo, si tu componente o directiva ha creado un observable o ha suscrito a uno, es posible que debas cancelar la suscripción para evitar fugas de memoria.
RxJS
RxJS (Reactive Extensions Library for JavaScript) es una popular librería de Javascript para el manejo de observables. Si trabajas con Angular esta librería será tu mejor amiga
Para cancelar una suscripción, debes almacenar la suscripción en una variable y luego llamar al método unsubscribe() en la variable cuando el componente se destruye. Aquí te presento un ejemplo:
En este ejemplo, el componente MiComponente tiene una propiedad subscription que almacena la suscripción al observable. En el constructor, se suscribe al observable a través del servicio MiServicio. Luego, en el método ngOnDestroy, se llama al método unsubscribe() en la variable subscription para cancelar la suscripción.
De esta manera, cuando el componente se destruye, la suscripción se cancela y los recursos asignados al observable se liberan, evitando posibles fugas de memoria.
Es importante identificar y corregir las fugas de memoria en Angular, ya que pueden provocar que la aplicación consuma más memoria de la necesaria, lo que puede afectar el rendimiento y la experiencia del usuario.
Input setter coercion
En Angular, los decoradores @Input se utilizan para exponer propiedades públicas de un componente para que puedan ser establecidas desde otros componentes. Cuando se establece el valor de una propiedad de entrada mediante @Input, Angular ejecuta automáticamente la lógica de detección de cambios para actualizar la vista y los modelos de datos correspondientes.
En algunos casos, es posible que desees aplicar una conversión o validación al valor de entrada antes de establecerlo en la propiedad del componente.
Por ejemplo, es posible que desees asegurarte de que un valor de entrada sea un número entero antes de establecerlo en una propiedad que espera un número.
Para abordar esta necesidad, Angular proporciona una característica llamada Input setter coercion. Este mecanismo permite definir un método de conversión o validación que se ejecuta automáticamente cuando se establece el valor de entrada de una propiedad del componente. Este método se define en la propiedad de entrada mediante un decorador @Input modificado con el modificador set.
El método de conversión o validación debe tener el mismo nombre que la propiedad de entrada, seguido de la palabra Change. El método toma un solo argumento que representa el nuevo valor de la propiedad de entrada. Aquí te presento un ejemplo de cómo se utiliza:
import{Component,Input}from'@angular/core';@Component({selector:'app-mi-componente',templateUrl:'./mi-componente.component.html',styleUrls:['./mi-componente.component.css']})exportclassMiComponente{private_miPropiedad: number; @Input()setmiPropiedad(value: number){this._miPropiedad=Math.floor(value);}getmiPropiedad(): number {returnthis._miPropiedad;}}
En este ejemplo, el componente MiComponente tiene una propiedad de entrada llamada miPropiedad, que se define mediante el decorador @Input. El método de conversión o validación se define mediante el modificador set y se llama miPropiedadChange. Este método utiliza la función Math.floor para convertir el valor de entrada a un número entero y establece el resultado en la propiedad privada _miPropiedad.
Es importante tener en cuenta que el método de conversión o validación solo se ejecuta cuando se establece el valor de entrada mediante la sintaxis de enlace de propiedades [miPropiedad]. Si se establece el valor de entrada directamente en la propiedad del componente, el método de conversión o validación no se ejecutará.
El mecanismo de Input setter coercion puede ser útil para simplificar el código y asegurar que los valores de entrada se ajusten a los requisitos del componente. Sin embargo, debes tener cuidado al utilizarlo para no introducir comportamientos inesperados o dificultades de depuración. Es importante documentar claramente la función de conversión o validación y asegurarse de que se comporte de manera consistente en todas las situaciones.
No veo un uso practico para el ngOnChange(), sería estupendo que nos mostrara como manipular cada cambio dentro del ngOnChange() el cual es el encargado de gestionar los cambios de estado de los @Inputs. pero por lo visto es mejor gestionarlos desde un setInput
ngOnDestroy(): Se llama solo una vez, justo antes de que Angular destruya el componente, y sirve para prevenir memory leaks, eliminando por ejemplo suscripciones a Observables e event handlers
Aqui les dejo un recurso de la documentacion oficial donde podemos complementar los ejemplos:
#AguanteAngular
Las clases me han parecido interesantes, pero cuando el profesor hace un comentario como setInterval realmente no es una buena práctica, uno esperaría que con su experiencia indicara como evitarlo, que otras alternativas existen, pero decir no es una buena práctica y vamos a usarla. Es algo contradictorio.
Te esta indicando como dejar de perpetuar la mala practica, como limpiar la suscripcion. Aparte, en los recursos te indican exactamente como hacer lo mismo pero usando rxjs, y los metodos subscribe y unsubscribe de la clase Suscription
Pienso que el SetInput debió venir como una clase después de la anterior que vimos y el ngDestroy después de la de SetInput.
no me funcona el boton para eliminar
toggleImg() {
this.showImg = !this.showImg;
}
Hola rosa. Verifica si inicializaste el método dentro del *ngIf. A mí me sucedió lo mismo y la solución fue que no había puesto los () jajaja
es complicado entender a la primera hay que repetir la clase y repasar, saludos yo también estoy aprendiendo.
8:25 se nota el corte con cambio de tema
Para los que estén realizando este curso recientemente y estén utilizando Angular 18 o posterior. Al utilizar window les generará unos errores debido a que Angular/cli en versiones posteriores a la 17 está utilizando el builder de Vite.
Comparto una posible solución a este error (TENER EN CUENTA DEMÁS IMPORTACIONES, ACÁ SOLO LES PUSE LAS QUE SE NECESITAN PARA SOLUCIONAR EL ERROR):
import { isPlatformBrowser } from '@angular/common';
Estoy haciendo una versión moderna del código del curso, ya que en la clase se utiliza el Angular clásico con @Input() y ngOnChanges().
En Angular 20, ahora podemos usar Signal Inputs (input()) y efectos reactivos (effect()) para detectar cambios de forma más limpia y reactiva, sin depender de los ciclos de vida como ngOnChanges.
import{AfterViewInit,Component, effect, input,OnDestroy,OnInit, output, signal,}from'@angular/core';@Component({selector:'app-img',standalone:false,templateUrl:'./img.html',styleUrl:'./img.scss',})exportclassImgComponentimplementsOnInit,AfterViewInit,OnDestroy{ img = input<string>('');// ✅ signal input loaded = output<string>();// ✅ signal output imgDefault ='https://plus.unsplash.com/premium_photo-1680371834101-b2ffbf3f7826?...'; currentImg = signal<string>(''); counter =0; counterFn?: number;constructor(){// ✅ Detecta los cambios en la señal "img" de forma reactivaeffect(()=>{console.log('🖼️ Imagen actualizada a =>',this.img());});}ngOnInit(){console.log('🧩 ngOnInit =>',this.img());this.counterFn=window.setInterval(()=>{this.counter++;console.log('⏱️ Contador =>',this.counter);},1000);}ngAfterViewInit(){console.log('✅ ngAfterViewInit =>',this.img());}ngOnDestroy(){console.log('🧹 ngOnDestroy =>',this.img());window.clearInterval(this.counterFn);}imgError(){this.currentImg.set(this.imgDefault);}imgLoaded(){console.log('📤 Imagen cargada desde el componente hijo');this.loaded.emit(this.img());}}
dificil de entender, muy complicada la explicacion, me termina de complicar pero se nota que nicolas es un trome.....
Profe, primera vez que me hizo ver la clase dos veces porque no le entendí el valor, o utilidad al setInput y porque utilizarlo sobre el ngOnChange
Lo que pasa es que en la función onChanges escucha los cambios de cualquier input, en el video puso de ejemplo al input "img", menciono que en caso de que tengas muchos inputs tendrías que verificar cual es haciendo uso de IFs por lo cual es mejor usar un SET, un SET para cada variable te permitirá en principio asignar el cambio y también añadir más código. Digamos que quieres que en el img en especifico haga un reset de otros inputs o una petición etc eso lo haces dentro de ese set y no dentro del onChanges de es forma no tendrías toda la lógica amontonada para cada input distinto en una misma función