Skip to content

injectAutoEffect

Created by Chau Tran

injectAutoEffect is a CIF that returns an auto-wired Effect, hence the name auto-effect. This Effect can be used in places that do not have an implicit Injection Context like ngOnInit or afterNextRender

import { injectAutoEffect } from 'ngxtension/auto-effect';

Usage

@Component()
export class MyComponent {
@Input({ required: true }) data!: Signal<Data>;
private autoEffect = injectAutoEffect();
constructor() {
// This WON'T WORK because `data` input has not been resolved yet
effect(() => {
console.log(this.data());
});
}
ngOnInit() {
// `data` Input is not resolved until `ngOnInit` is invoked
this.autoEffect(() => {
console.log(this.data());
});
}
}

Clean up function

Normal effect() can optionally invoke onCleanup argument to run some clean-up logic every time the Effect invokes.

effect((onCleanup) => {
const sub = interval(1000).subscribe():
onCleanup(() => sub.unsubscribe());
})

injectAutoEffect() allows the consumers to return a CleanUpFn instead. This is purely preference and has no affect on performance of effect()

const autoEffect = injectAutoEffect();
autoEffect(() => {
const sub = interval(1000).subscribe():
return () => sub.unsubscribe();
})

Nested Effect

For normal effect, we always need to pass in the Injector to the 2nd parameter of nested effect().

effect((onCleanup) => {
const innerEffectRef = effect(
() => {
/* inner effect logic */
},
{ manualCleanup: true, injector: injector },
);
onCleanup(() => innerEffectRef.destroy());
});

For injectAutoEffect(), autoEffect will always be invoked with the initial Injector (where we invoke injectAutoEffect()).

const autoEffect = injectAutoEffect();
autoEffect(() => {
const innerEffectRef = autoEffect(
() => {
/* inner effect logic */
},
{ manualCleanup: true },
);
return () => innerEffectRef.destroy();
});

Optionally, autoEffect callback exposes the Injector so consumers can make use of that if needed

const autoEffect = injectAutoEffect();
autoEffect((injector) => {
/* do something */
});