My use case: Use a reactive rxDB.collection.find().$$() inside a computed angular signal. I am quite sure I am misreading the current documentation :/
Reading the current RxDB documentation I can see that I can make RxDB provide Angular Signals via the reactivityFactory (awesome!!!). If I follow the documentation I end up with an NG0602
error since we cannot create signals within a reactive context. See: https://stackblitz.com/edit/rxdb-15-angular-17-playground-azqzjo?file=src%2Fapp%2Fapp.component.ts
The issue comes from the fact, that
protected cars = computed(() => {
if (this.isLoading()) return [];
return this.db.cars.find().$$();
});
internally calls the reactivityFactory.
If I work around this issue e.g. by using the toLazySignal
util from ngxtension
it creates a signal everytime a collection change happens, see https://stackblitz.com/edit/rxdb-15-angular-17-playground-1ky4q9?file=src%2Fapp%2Fapp.component.ts (open the browser console)
How should I implement the reactivityFactory corretly so that my use case works?
Solved! The issue was a total different one. The observable actually returned an error, which was swallowed by toSignal
.
The error:
Error (QU13): RxError (QU13):
A top level field of the query is not included in the schema
Given parameters: {
schema:{
"additionalProperties": false,
"encrypted": [],
"indexes": [
...
That was the reason why the signal got create again immediately which created an endless loop that ended in a browser crash. Adding rejectErrors: true
to the toSignal options helped a lot.
So the reactivity factory should be something like this:
export function createReactivityFactory(injector: Injector): RxReactivityFactory<Signal<any>> {
return {
fromObservable(observable$, initialValue: any) {
return untracked(() =>
toSignal(observable$, {
initialValue,
injector,
rejectErrors: true
})
);
}
};
}
Edit: The updated documentation: https://rxdb.info/reactivity.html#adding-a-custom-reactivity-factory-in-angular-projects