Skip to content

Commit 5aad08b

Browse files
committed
feat(core): allow injectBeforeRender to accept priority as signal
1 parent 080c7c7 commit 5aad08b

File tree

1 file changed

+28
-22
lines changed

1 file changed

+28
-22
lines changed

libs/core/src/lib/utils/before-render.ts

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { DestroyRef, Injector, inject } from '@angular/core';
1+
import { DestroyRef, effect, inject, Injector } from '@angular/core';
22
import { assertInjector } from 'ngxtension/assert-injector';
33
import { injectStore } from '../store';
44
import type { NgtBeforeRenderRecord } from '../types';
@@ -7,35 +7,41 @@ import type { NgtBeforeRenderRecord } from '../types';
77
* `injectBeforeRender` invokes its callback on every frame. Hence, the notion of tracking
88
* changes (i.e: signals) does not really matter since we're getting latest values of the things we need on every frame anyway.
99
*
10-
* If `priority` is dynamic, consumers should set up `injectBeforeRender` in
11-
* an `effect` and track `priority` changes. Make use of `onCleanup` to clean up
12-
* previous before render subscription
10+
* If `priority` is a Signal, `injectBeforeRender` will set up an Effect internally and returns the `EffectRef#destroy` instead.
1311
*
1412
* @example
1513
* ```ts
16-
* const injector = inject(Injector);
17-
*
18-
* effect((onCleanup) => {
19-
* const priority = this.priority(); // track priority
20-
*
21-
* const sub = injectBeforeRender(
22-
* ({ gl, camera }) => {
23-
* // before render logic
24-
* },
25-
* {
26-
* priority,
27-
* injector, // injector is needed since injectBeforeRender is invoked in effect body
28-
* }
29-
* });
30-
*
31-
* onCleanup(() => sub());
32-
* });
14+
* const destroy = injectBeforeRender(
15+
* ({ gl, camera }) => {
16+
* // before render logic
17+
* },
18+
* {
19+
* priority: this.priority, // this.priority is a Signal<number>
20+
* }
21+
* )
3322
* ```
3423
*/
3524
export function injectBeforeRender(
3625
cb: NgtBeforeRenderRecord['callback'],
37-
{ priority = 0, injector }: { priority?: number; injector?: Injector } = {},
26+
{ priority = 0, injector }: { priority?: number | (() => number); injector?: Injector } = {},
3827
) {
28+
if (typeof priority === 'function') {
29+
const effectRef = assertInjector(injectBeforeRender, injector, () => {
30+
const store = injectStore();
31+
const ref = effect((onCleanup) => {
32+
const p = priority();
33+
const sub = store.snapshot.internal.subscribe(cb, p, store);
34+
onCleanup(() => sub());
35+
});
36+
37+
inject(DestroyRef).onDestroy(() => void ref.destroy());
38+
39+
return ref;
40+
});
41+
42+
return effectRef.destroy.bind(effectRef);
43+
}
44+
3945
return assertInjector(injectBeforeRender, injector, () => {
4046
const store = injectStore();
4147
const sub = store.snapshot.internal.subscribe(cb, priority, store);

0 commit comments

Comments
 (0)