Skip to content

Commit e2f1e57

Browse files
03byronMikeRyanDev
authored andcommitted
fix(createSelector): memoize projector function (#228)
Closes #226
1 parent c79853b commit e2f1e57

File tree

2 files changed

+26
-4
lines changed

2 files changed

+26
-4
lines changed

modules/store/spec/selector.spec.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,23 @@ describe('Selectors', () => {
4141
expect(projectFn).toHaveBeenCalledWith(countOne, countTwo);
4242
});
4343

44+
it('should call the projector function only when the value of a dependent selector change', () => {
45+
const firstState = { first: 'state', unchanged: 'state' };
46+
const secondState = { second: 'state', unchanged: 'state' };
47+
const neverChangingSelector = jasmine
48+
.createSpy('unchangedSelector')
49+
.and.callFake((state: any) => {
50+
return state.unchanged;
51+
});
52+
const projectFn = jasmine.createSpy('projectionFn');
53+
const selector = createSelector(neverChangingSelector, projectFn);
54+
55+
selector(firstState);
56+
selector(secondState);
57+
58+
expect(projectFn).toHaveBeenCalledTimes(1);
59+
});
60+
4461
it('should memoize the function', () => {
4562
const firstState = { first: 'state' };
4663
const secondState = { second: 'state' };

modules/store/src/selector.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,19 +115,24 @@ export function createSelector(...args: any[]): Selector<any, any> {
115115
selector.release && typeof selector.release === 'function'
116116
);
117117

118-
const { memoized, reset } = memoize(function(state: any) {
118+
const memoizedProjector = memoize(function(...selectors: any[]) {
119+
return projector.apply(null, selectors);
120+
});
121+
122+
const memoizedState = memoize(function(state: any) {
119123
const args = selectors.map(fn => fn(state));
120124

121-
return projector.apply(null, args);
125+
return memoizedProjector.memoized.apply(null, args);
122126
});
123127

124128
function release() {
125-
reset();
129+
memoizedState.reset();
130+
memoizedProjector.reset();
126131

127132
memoizedSelectors.forEach(selector => selector.release());
128133
}
129134

130-
return Object.assign(memoized, { release });
135+
return Object.assign(memoizedState.memoized, { release });
131136
}
132137

133138
export function createFeatureSelector<T>(

0 commit comments

Comments
 (0)