Skip to content

Commit

Permalink
fix(RouterStore): Add generic type to RouterReducerState (#292)
Browse files Browse the repository at this point in the history
Closes #289
  • Loading branch information
brandonroberts authored and MikeRyanDev committed Aug 17, 2017
1 parent bf7f70c commit 6da3ec5
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 30 deletions.
22 changes: 17 additions & 5 deletions docs/router-store/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,43 @@ issues when used with the Store Devtools. In most cases, you may only need a pie
To use the time-traveling debugging in the Devtools, you must return an object containing the `url` when using the `routerReducer`.

```ts
import { StoreModule } from '@ngrx/store';
import { StoreModule, ActionReducerMap } from '@ngrx/store';
import { Params } from '@angular/router';
import {
StoreRouterConnectingModule,
routerReducer,
RouterReducerState,
RouterStateSerializer,
RouterStateSnapshotType
RouterStateSnapshot
} from '@ngrx/router-store';

export interface RouterStateUrl {
url: string;
queryParams: Params;
}

export interface State {
routerReducer: RouterReducerState<RouterStateUrl>;
}

export class CustomSerializer implements RouterStateSerializer<RouterStateUrl> {
serialize(routerState: RouterStateSnapshot): RouterStateUrl {
const { url } = routerState;
const queryParams = routerState.root.queryParams;

// Only return an object including the URL
// Only return an object including the URL and query params
// instead of the entire snapshot
return { url };
return { url, queryParams };
}
}

export const reducers: ActionReducerMap<State> = {
routerReducer: routerReducer
};

@NgModule({
imports: [
StoreModule.forRoot({ routerReducer: routerReducer }),
StoreModule.forRoot(reducers),
RouterModule.forRoot([
// routes
]),
Expand Down
3 changes: 2 additions & 1 deletion example-app/app/reducers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
MetaReducer,
} from '@ngrx/store';
import { environment } from '../../environments/environment';
import { RouterStateUrl } from '../shared/utils';
import * as fromRouter from '@ngrx/router-store';

/**
Expand All @@ -23,7 +24,7 @@ import * as fromLayout from '../core/reducers/layout';
*/
export interface State {
layout: fromLayout.State;
routerReducer: fromRouter.RouterReducerState;
routerReducer: fromRouter.RouterReducerState<RouterStateUrl>;
}

/**
Expand Down
10 changes: 6 additions & 4 deletions example-app/app/shared/utils.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
import { RouterStateSerializer } from '@ngrx/router-store';
import { RouterStateSnapshot } from '@angular/router';
import { RouterStateSnapshot, Params } from '@angular/router';

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

export interface RouterStateUrl {
url: string;
queryParams: Params;
}

export class CustomRouterStateSerializer
implements RouterStateSerializer<RouterStateUrl> {
serialize(routerState: RouterStateSnapshot): RouterStateUrl {
const { url } = routerState;
const queryParams = routerState.root.queryParams;

return { url };
return { url, queryParams };
}
}
15 changes: 12 additions & 3 deletions modules/router-store/spec/integration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,11 +325,13 @@ describe('integration spec', () => {
: null;
};

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

return { url };
return { url, params };
}
}

Expand All @@ -353,7 +355,14 @@ describe('integration spec', () => {
expect(log).toEqual([
{ type: 'router', event: 'NavigationStart', url: '/next' },
{ type: 'router', event: 'RoutesRecognized', url: '/next' },
{ type: 'store', state: { url: '/next-custom', navigationId: 2 } },
{
type: 'store',
state: {
url: '/next-custom',
navigationId: 2,
params: { test: 1 },
},
},
{ type: 'router', event: 'NavigationEnd', url: '/next' },
]);
log.splice(0);
Expand Down
34 changes: 17 additions & 17 deletions modules/router-store/src/router_store_module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export type RouterNavigationPayload<T> = {
/**
* An action dispatched when the router navigates.
*/
export type RouterNavigationAction<T> = {
export type RouterNavigationAction<T = RouterStateSnapshot> = {
type: typeof ROUTER_NAVIGATION;
payload: RouterNavigationPayload<T>;
};
Expand All @@ -41,18 +41,18 @@ export const ROUTER_CANCEL = 'ROUTER_CANCEL';
/**
* Payload of ROUTER_CANCEL.
*/
export type RouterCancelPayload<T> = {
routerState: RouterStateSnapshot;
export type RouterCancelPayload<T, V> = {
routerState: V;
storeState: T;
event: NavigationCancel;
};

/**
* An action dispatched when the router cancel navigation.
*/
export type RouterCancelAction<T> = {
export type RouterCancelAction<T, V = RouterStateSnapshot> = {
type: typeof ROUTER_CANCEL;
payload: RouterCancelPayload<T>;
payload: RouterCancelPayload<T, V>;
};

/**
Expand All @@ -63,37 +63,37 @@ export const ROUTER_ERROR = 'ROUTE_ERROR';
/**
* Payload of ROUTER_ERROR.
*/
export type RouterErrorPayload<T> = {
routerState: RouterStateSnapshot;
export type RouterErrorPayload<T, V> = {
routerState: V;
storeState: T;
event: NavigationError;
};

/**
* An action dispatched when the router errors.
*/
export type RouterErrorAction<T> = {
export type RouterErrorAction<T, V = RouterStateSnapshot> = {
type: typeof ROUTER_ERROR;
payload: RouterErrorPayload<T>;
payload: RouterErrorPayload<T, V>;
};

/**
* An union type of router actions.
*/
export type RouterAction<T> =
export type RouterAction<T, V = RouterStateSnapshot> =
| RouterNavigationAction<T>
| RouterCancelAction<T>
| RouterErrorAction<T>;
| RouterCancelAction<T, V>
| RouterErrorAction<T, V>;

export type RouterReducerState = {
state: RouterStateSnapshot;
export type RouterReducerState<T = RouterStateSnapshot> = {
state: T;
navigationId: number;
};

export function routerReducer(
state: RouterReducerState,
export function routerReducer<T = RouterStateSnapshot>(
state: RouterReducerState<T>,
action: RouterAction<any>
): RouterReducerState {
): RouterReducerState<T> {
switch (action.type) {
case ROUTER_NAVIGATION:
case ROUTER_ERROR:
Expand Down

0 comments on commit 6da3ec5

Please sign in to comment.