Skip to content

beforeRender

beforeRender is a Custom Inject Function that allows you to execute logic before each frame render. This is useful for animations, updates, or any computations that need to happen on every frame.

Usage

beforeRender requires a before render callback. This callback is invoked on every frame with NgtRenderState

export interface NgtRenderState extends NgtState {
delta: number;
frame?: XRFrame;
}

Check out Store section for details on NgtState.

export class MyCmp {
constructor() {
beforeRender(({ camera, delta }) => {
camera.position.x = Math.sin(Date.now() / 1000) * delta;
});
}
}

Optional injector

Since beforeRender is a CIF, it has to be invoked in an Injection Context. In order to invoke beforeRender outside of an Injection Context, you can provide an Injector to the injector property of the 2nd argument to beforeRender

export class MyCmp {
constructor() {
const injector = inject(Injector);
afterNextRender(() => {
// outside of Injection Context, provide Injector ✅
beforeRender(() => {}, { injector })
})
}
}

Optional priority

The priority parameter determines the order of execution when multiple before render callbacks are registered:

// executes first
beforeRender(cb1, { priority: 1 });
// executes second
beforeRender(cb2, { priority: 2 });

priority can also be dynamic using a Signal<number>

export class MyCmp {
priority = input(0);
constructor() {
beforeRender(
({ camera, delta }) => {
camera.position.x = Math.sin(Date.now() / 1000) * delta;
},
{
priority: this.priority
}
);
}
}

How it works

beforeRender subscribes to the internal render loop of Angular Three.

When using a static priority number, it returns an unsubscribe function, but you typically don’t need to use it as it’s automatically handled by Angular’s DestroyRef

When using a dynamic priority, it sets up an internal effect and returns the EffectRef#destroy function. Again, cleanup is automatically handled through DestroyRef.