From 1ea26f12acbb7c74f109b7c5398b24599691011b Mon Sep 17 00:00:00 2001 From: mikezks <23002661+mikezks@users.noreply.github.com> Date: Mon, 8 May 2023 14:58:23 +0200 Subject: [PATCH 1/3] fix(store): add Signal equal function for immutable object comparison (#3882) --- modules/store/src/store.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/store/src/store.ts b/modules/store/src/store.ts index b8e69e0896..c8a054b407 100644 --- a/modules/store/src/store.ts +++ b/modules/store/src/store.ts @@ -112,7 +112,9 @@ export class Store selector: (state: T) => K, options?: SelectSignalOptions ): Signal { - return computed(() => selector(this.state()), { equal: options?.equal }); + return computed(() => selector(this.state()), { + equal: options?.equal || ((previous, current) => previous === current), + }); } override lift(operator: Operator): Store { From dfdca6fa5979fb3189fc608cd8c596a26d521e47 Mon Sep 17 00:00:00 2001 From: mikezks <23002661+mikezks@users.noreply.github.com> Date: Mon, 8 May 2023 16:22:03 +0200 Subject: [PATCH 2/3] test(store): selectSignal immutable state update trigger (#3882) --- .../store/spec/integration_signals.spec.ts | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/modules/store/spec/integration_signals.spec.ts b/modules/store/spec/integration_signals.spec.ts index 776727b333..0014542264 100644 --- a/modules/store/spec/integration_signals.spec.ts +++ b/modules/store/spec/integration_signals.spec.ts @@ -12,6 +12,7 @@ import { VisibilityFilters, resetId, } from './fixtures/todos'; +import { computed } from '@angular/core'; interface Todo { id: number; @@ -130,4 +131,30 @@ describe('NgRx and Signals Integration spec', () => { expect(error).toBeUndefined(); }); }); + + describe('immutable state integration spec', () => { + it('Store.selectSignal should not trigger on unrelated global state changes', () => { + let todosTriggerCount = 0; + + const todos = TestBed.runInInjectionContext(() => + store.selectSignal((state) => state.todos) + ); + + const todosTriggerState = TestBed.runInInjectionContext(() => + computed(() => { + todos(); + return ++todosTriggerCount; + }) + ); + + store.dispatch({ type: ADD_TODO, payload: { text: 'first todo' } }); + expect(todosTriggerState()).toBe(1); + + store.dispatch({ + type: SET_VISIBILITY_FILTER, + payload: VisibilityFilters.SHOW_ACTIVE, + }); + expect(todosTriggerState()).toBe(1); + }); + }); }); From 57c26391a9870c5ab67c4c7a71de287056009b9c Mon Sep 17 00:00:00 2001 From: Brandon Roberts Date: Mon, 8 May 2023 15:40:15 -0500 Subject: [PATCH 3/3] chore: test without injection context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Marko Stanimirović --- modules/store/spec/integration_signals.spec.ts | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/modules/store/spec/integration_signals.spec.ts b/modules/store/spec/integration_signals.spec.ts index 0014542264..342662eb0f 100644 --- a/modules/store/spec/integration_signals.spec.ts +++ b/modules/store/spec/integration_signals.spec.ts @@ -136,16 +136,12 @@ describe('NgRx and Signals Integration spec', () => { it('Store.selectSignal should not trigger on unrelated global state changes', () => { let todosTriggerCount = 0; - const todos = TestBed.runInInjectionContext(() => - store.selectSignal((state) => state.todos) - ); - - const todosTriggerState = TestBed.runInInjectionContext(() => - computed(() => { - todos(); - return ++todosTriggerCount; - }) - ); + const todos = store.selectSignal((state) => state.todos); + + const todosTriggerState = computed(() => { + todos(); + return ++todosTriggerCount; + }); store.dispatch({ type: ADD_TODO, payload: { text: 'first todo' } }); expect(todosTriggerState()).toBe(1);