Somtimes when i write effects i end up having depencies that re run the effect in nested functions i made this so it was easier for me to understand exactly which one will re run the effect has the same footgun as react use effect, this makes working with effects easier, your thoughts ?
import {
CreateEffectOptions,
effect,
EffectCleanupRegisterFn,
EffectRef,
Signal,
untracked,
} from '@angular/core';
// Extract the inner type from a Signal
type SignalValue<T> = T extends Signal<infer V> ? V : never;
// Map a tuple of Signals to a tuple of their value types
type DependenciesValues<T extends readonly Signal<unknown>[]> = {
[K in keyof T]: SignalValue<T[K]>;
};
export const useEffect = <const T extends readonly Signal<unknown>[]>(
callback: (...values: DependenciesValues<T>) => void | Promise<void>,
dependencies: T,
options: CreateEffectOptions = {},
): EffectRef => {
return effect(
async () => {
const values = dependencies.map((dep) => dep()) as DependenciesValues<T>;
untracked(() => {
callback(...values);
});
},
{
...options,
},
);
};
Here is example usage
export class AppComponent {
foo = signal('');
constructor() {
useEffect(
(value) => {
console.log('Use effect ran ', value);
},
[this.foo],
);
setTimeout(() => {
this.foo.set('Bar');
console.log('Efect ran');
}, 5000);
}
}