Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: use untracked internally for signal state stream
Browse files Browse the repository at this point in the history
markwhitfeld committed Aug 6, 2024

Verified

This commit was signed with the committer’s verified signature.
jalaziz Jameel Al-Aziz
1 parent 54bfc1a commit 0a67567
Showing 5 changed files with 33 additions and 27 deletions.
21 changes: 21 additions & 0 deletions packages/store/internals/src/custom-rxjs-operators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { MonoTypeOperatorFunction, Observable } from 'rxjs';

export function ɵwrapObserverCalls<TValue>(
invokeFn: (fn: () => void) => void
): MonoTypeOperatorFunction<TValue> {
return (source: Observable<TValue>) => {
return new Observable<TValue>(subscriber => {
return source.subscribe({
next(value) {
invokeFn(() => subscriber.next(value));
},
error(error) {
invokeFn(() => subscriber.error(error));
},
complete() {
invokeFn(() => subscriber.complete());
}
});
});
};
}
1 change: 1 addition & 0 deletions packages/store/internals/src/index.ts
Original file line number Diff line number Diff line change
@@ -6,4 +6,5 @@ export { ɵINITIAL_STATE_TOKEN, ɵInitialState } from './initial-state';
export { ɵNgxsAppBootstrappedState } from './ngxs-app-bootstrapped-state';
export { ɵNGXS_STATE_CONTEXT_FACTORY, ɵNGXS_STATE_FACTORY } from './internal-tokens';
export { ɵOrderedSubject, ɵOrderedBehaviorSubject } from './custom-rxjs-subjects';
export { ɵwrapObserverCalls } from './custom-rxjs-operators';
export { ɵStateStream } from './state-stream';
7 changes: 4 additions & 3 deletions packages/store/internals/src/state-stream.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { Injectable, OnDestroy, Signal } from '@angular/core';
import { Injectable, OnDestroy, Signal, untracked } from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';

import { ɵPlainObject } from './symbols';
import { ɵwrapObserverCalls } from './custom-rxjs-operators';
import { ɵOrderedBehaviorSubject } from './custom-rxjs-subjects';
import { ɵPlainObject } from './symbols';

/**
* BehaviorSubject of the entire state.
* @ignore
*/
@Injectable({ providedIn: 'root' })
export class ɵStateStream extends ɵOrderedBehaviorSubject<ɵPlainObject> implements OnDestroy {
readonly state: Signal<ɵPlainObject> = toSignal(this, {
readonly state: Signal<ɵPlainObject> = toSignal(this.pipe(ɵwrapObserverCalls(untracked)), {
manualCleanup: true,
requireSync: true
});
22 changes: 3 additions & 19 deletions packages/store/src/operators/leave-ngxs.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,10 @@
import { MonoTypeOperatorFunction, Observable, Observer } from 'rxjs';
import { ɵwrapObserverCalls } from '@ngxs/store/internals';
import { NgxsExecutionStrategy } from '../execution/symbols';

/**
* Returns operator that will run
* `subscribe` outside of the ngxs execution context
*/
export function leaveNgxs<T>(
ngxsExecutionStrategy: NgxsExecutionStrategy
): MonoTypeOperatorFunction<T> {
return (source: Observable<T>) => {
return new Observable((sink: Observer<T>) => {
return source.subscribe({
next(value) {
ngxsExecutionStrategy.leave(() => sink.next(value));
},
error(error) {
ngxsExecutionStrategy.leave(() => sink.error(error));
},
complete() {
ngxsExecutionStrategy.leave(() => sink.complete());
}
});
});
};
export function leaveNgxs<T>(ngxsExecutionStrategy: NgxsExecutionStrategy) {
return ɵwrapObserverCalls<T>(fn => ngxsExecutionStrategy.leave(fn));
}
Original file line number Diff line number Diff line change
@@ -4,8 +4,7 @@ import {
Injectable,
effect,
provideExperimentalZonelessChangeDetection,
signal,
untracked
signal
} from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { bootstrapApplication } from '@angular/platform-browser';
@@ -75,7 +74,7 @@ describe('State per signal', () => {
constructor(private store: Store) {
effect(() => {
const value = this.value();
untracked(() => store.dispatch(new SetNumber(value)));
store.dispatch(new SetNumber(value));
});
}

@@ -125,8 +124,8 @@ describe('State per signal', () => {
constructor(store: Store) {
effect(() => {
const value = this.value();
untracked(() => store.dispatch(new SetNumber(value)));
untracked(() => store.dispatch(new SetNumberAsynchronously(value + 100)));
store.dispatch(new SetNumber(value));
store.dispatch(new SetNumberAsynchronously(value + 100));
});
}

0 comments on commit 0a67567

Please sign in to comment.