1- import { DestroyRef , Injector , inject } from '@angular/core' ;
1+ import { DestroyRef , effect , inject , Injector } from '@angular/core' ;
22import { assertInjector } from 'ngxtension/assert-injector' ;
33import { injectStore } from '../store' ;
44import 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 */
3524export 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