Skip to content

Commit 6da3ec5

Browse files
brandonrobertsMikeRyanDev
authored andcommitted
fix(RouterStore): Add generic type to RouterReducerState (#292)
Closes #289
1 parent bf7f70c commit 6da3ec5

5 files changed

Lines changed: 54 additions & 30 deletions

File tree

docs/router-store/api.md

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,31 +8,43 @@ issues when used with the Store Devtools. In most cases, you may only need a pie
88
To use the time-traveling debugging in the Devtools, you must return an object containing the `url` when using the `routerReducer`.
99

1010
```ts
11-
import { StoreModule } from '@ngrx/store';
11+
import { StoreModule, ActionReducerMap } from '@ngrx/store';
12+
import { Params } from '@angular/router';
1213
import {
1314
StoreRouterConnectingModule,
1415
routerReducer,
16+
RouterReducerState,
1517
RouterStateSerializer,
16-
RouterStateSnapshotType
18+
RouterStateSnapshot
1719
} from '@ngrx/router-store';
1820

1921
export interface RouterStateUrl {
2022
url: string;
23+
queryParams: Params;
24+
}
25+
26+
export interface State {
27+
routerReducer: RouterReducerState<RouterStateUrl>;
2128
}
2229

2330
export class CustomSerializer implements RouterStateSerializer<RouterStateUrl> {
2431
serialize(routerState: RouterStateSnapshot): RouterStateUrl {
2532
const { url } = routerState;
33+
const queryParams = routerState.root.queryParams;
2634

27-
// Only return an object including the URL
35+
// Only return an object including the URL and query params
2836
// instead of the entire snapshot
29-
return { url };
37+
return { url, queryParams };
3038
}
3139
}
3240

41+
export const reducers: ActionReducerMap<State> = {
42+
routerReducer: routerReducer
43+
};
44+
3345
@NgModule({
3446
imports: [
35-
StoreModule.forRoot({ routerReducer: routerReducer }),
47+
StoreModule.forRoot(reducers),
3648
RouterModule.forRoot([
3749
// routes
3850
]),

example-app/app/reducers/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
MetaReducer,
77
} from '@ngrx/store';
88
import { environment } from '../../environments/environment';
9+
import { RouterStateUrl } from '../shared/utils';
910
import * as fromRouter from '@ngrx/router-store';
1011

1112
/**
@@ -23,7 +24,7 @@ import * as fromLayout from '../core/reducers/layout';
2324
*/
2425
export interface State {
2526
layout: fromLayout.State;
26-
routerReducer: fromRouter.RouterReducerState;
27+
routerReducer: fromRouter.RouterReducerState<RouterStateUrl>;
2728
}
2829

2930
/**

example-app/app/shared/utils.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
11
import { RouterStateSerializer } from '@ngrx/router-store';
2-
import { RouterStateSnapshot } from '@angular/router';
2+
import { RouterStateSnapshot, Params } from '@angular/router';
33

44
/**
55
* The RouterStateSerializer takes the current RouterStateSnapshot
66
* and returns any pertinent information needed. The snapshot contains
77
* all information about the state of the router at the given point in time.
88
* The entire snapshot is complex and not always needed. In this case, you only
9-
* need the URL from the snapshot in the store. Other items could be
10-
* returned such as route parameters, query parameters and static route data.
9+
* need the URL and query parameters from the snapshot in the store. Other items could be
10+
* returned such as route parameters and static route data.
1111
*/
1212

1313
export interface RouterStateUrl {
1414
url: string;
15+
queryParams: Params;
1516
}
1617

1718
export class CustomRouterStateSerializer
1819
implements RouterStateSerializer<RouterStateUrl> {
1920
serialize(routerState: RouterStateSnapshot): RouterStateUrl {
2021
const { url } = routerState;
22+
const queryParams = routerState.root.queryParams;
2123

22-
return { url };
24+
return { url, queryParams };
2325
}
2426
}

modules/router-store/spec/integration.spec.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -325,11 +325,13 @@ describe('integration spec', () => {
325325
: null;
326326
};
327327

328-
class CustomSerializer implements RouterStateSerializer<{ url: string }> {
328+
class CustomSerializer
329+
implements RouterStateSerializer<{ url: string; params: any }> {
329330
serialize(routerState: RouterStateSnapshot) {
330331
const url = `${routerState.url}-custom`;
332+
const params = { test: 1 };
331333

332-
return { url };
334+
return { url, params };
333335
}
334336
}
335337

@@ -353,7 +355,14 @@ describe('integration spec', () => {
353355
expect(log).toEqual([
354356
{ type: 'router', event: 'NavigationStart', url: '/next' },
355357
{ type: 'router', event: 'RoutesRecognized', url: '/next' },
356-
{ type: 'store', state: { url: '/next-custom', navigationId: 2 } },
358+
{
359+
type: 'store',
360+
state: {
361+
url: '/next-custom',
362+
navigationId: 2,
363+
params: { test: 1 },
364+
},
365+
},
357366
{ type: 'router', event: 'NavigationEnd', url: '/next' },
358367
]);
359368
log.splice(0);

modules/router-store/src/router_store_module.ts

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export type RouterNavigationPayload<T> = {
2828
/**
2929
* An action dispatched when the router navigates.
3030
*/
31-
export type RouterNavigationAction<T> = {
31+
export type RouterNavigationAction<T = RouterStateSnapshot> = {
3232
type: typeof ROUTER_NAVIGATION;
3333
payload: RouterNavigationPayload<T>;
3434
};
@@ -41,18 +41,18 @@ export const ROUTER_CANCEL = 'ROUTER_CANCEL';
4141
/**
4242
* Payload of ROUTER_CANCEL.
4343
*/
44-
export type RouterCancelPayload<T> = {
45-
routerState: RouterStateSnapshot;
44+
export type RouterCancelPayload<T, V> = {
45+
routerState: V;
4646
storeState: T;
4747
event: NavigationCancel;
4848
};
4949

5050
/**
5151
* An action dispatched when the router cancel navigation.
5252
*/
53-
export type RouterCancelAction<T> = {
53+
export type RouterCancelAction<T, V = RouterStateSnapshot> = {
5454
type: typeof ROUTER_CANCEL;
55-
payload: RouterCancelPayload<T>;
55+
payload: RouterCancelPayload<T, V>;
5656
};
5757

5858
/**
@@ -63,37 +63,37 @@ export const ROUTER_ERROR = 'ROUTE_ERROR';
6363
/**
6464
* Payload of ROUTER_ERROR.
6565
*/
66-
export type RouterErrorPayload<T> = {
67-
routerState: RouterStateSnapshot;
66+
export type RouterErrorPayload<T, V> = {
67+
routerState: V;
6868
storeState: T;
6969
event: NavigationError;
7070
};
7171

7272
/**
7373
* An action dispatched when the router errors.
7474
*/
75-
export type RouterErrorAction<T> = {
75+
export type RouterErrorAction<T, V = RouterStateSnapshot> = {
7676
type: typeof ROUTER_ERROR;
77-
payload: RouterErrorPayload<T>;
77+
payload: RouterErrorPayload<T, V>;
7878
};
7979

8080
/**
8181
* An union type of router actions.
8282
*/
83-
export type RouterAction<T> =
83+
export type RouterAction<T, V = RouterStateSnapshot> =
8484
| RouterNavigationAction<T>
85-
| RouterCancelAction<T>
86-
| RouterErrorAction<T>;
85+
| RouterCancelAction<T, V>
86+
| RouterErrorAction<T, V>;
8787

88-
export type RouterReducerState = {
89-
state: RouterStateSnapshot;
88+
export type RouterReducerState<T = RouterStateSnapshot> = {
89+
state: T;
9090
navigationId: number;
9191
};
9292

93-
export function routerReducer(
94-
state: RouterReducerState,
93+
export function routerReducer<T = RouterStateSnapshot>(
94+
state: RouterReducerState<T>,
9595
action: RouterAction<any>
96-
): RouterReducerState {
96+
): RouterReducerState<T> {
9797
switch (action.type) {
9898
case ROUTER_NAVIGATION:
9999
case ROUTER_ERROR:

0 commit comments

Comments
 (0)