I followed platform/MIGRATION.md guide to upgrade to v4. After I did all before/after steps, I got the following errors. The guide does not say anything how to deal with these issues.
Your second problem can be solved by removing the old ngrx/core code from your application, as (now) described in the migration guide: https://github.com/ngrx/platform/blob/master/MIGRATION.md#ngrxcore
The first can happen if you have something like .map(action => action.payload) in your code.
One easy fix for this is to replace such a mapping with .map(toPayload), from effects module. you can also use a type hint to tell the compiler exactly what type the action is. Unfortunately, the ofType filter doesn't allow type information for the exact action type, and payload is no longer part of the action interface, it seems.
Would it be possible to update the migration guide to mention the change to the action interface?
@alexjlockwood Yes, we would accept a PR that added a note about the Action interface
I don't think I am the right person to write the PR because I'm not aware of the reasoning/context behind the change.
Thanks a lot for quick response.
return Object.assign({}, action.payload);
import '@ngrx/core/add/operator/select';
export function getSubTitleSelector(state$: Observable<LayoutState>) {
return state$.select(state => state.subTitle);
}
Now select operator is gone? What should i do with this code?
Before the update, I had a MockStore class that extended Store. A bunch of the public Store member/method types have changed in the new update, so I had to change a bunch of stuff. Here was my final result:
import { ActionsSubject, ReducerManager, StateObservable, Store } from '@ngrx/store';
import { State, prodReducer } from 'app/my/custom/codebase/path';
import { map } from 'rxjs/operator/map';
export class MockStore extends Store<State> {
constructor() {
super(
undefined as StateObservable,
undefined as ActionsSubject,
undefined as ReducerManager,
);
}
select<T>(mapFn: (state: State) => T): Store<T> {
return map.call(this.subject, mapFn);
}
dispatch(action: Action) {}
// ...
}
export function taskReducer(
state = taskInitialState,
action: Action & { payload?: any }
): TaskState {}
You can also create a custom Action type in your application:
export interface AppAction {
type: string;
payload?: any;
}
Or, if you declare your actions as classes:
export type TaskAction
= LoadAction
| LoadCompletedAction
| LoadErrorAction
| CreateAction
| CreateCompletedAction;
you can pas your Action type to the reducer:
export function taskReducer(
state = taskInitialState, action: TaskAction): TaskState {}
My actions are not defined as classes, but as methods of an Action service.
getTasks() {
return this.store.select('tasks')
.map((state: TaskState) => state.tasks);
}
or
findById(record: {id}) {
return this.getTasks()
.filter(item => item['id'] === record['id']);
}
The migration guide also fails to mention the new type that was added: ActionReducerMap<T>
Without this type, I was unable to use compose() without a compiler error.
Thanks @loiane.
Any idea why payload was remove from Action? Does it mean that each project should create its own extension of Action type?
@alexjlockwood can you explain maybe why you're mocking store? it doesn't have any side effects, and works synchronously, so I don't see a huge amount of value in mocking it?
@robwormald My initial intention was to ensure that my UI tests were unaffected by the actual logic happening inside of my data store... so I could just test that certain actions are being dispatched and then test the data store separately in a different set of reducer-specific unit tests.
I would really appreciate having a higher level explanation as to why 'payload' was removed, and what kind of architecture should replace it. If the action is no longer able to pass data then how are new data values (from a backend) supposed to wind up in the store? Certainly not everything is about incrementing and decrementing a number. How are we supposed to handle data entry... or anything that can't be demonstrated by a static action type?
Also the migration section has a "before/after" section that are identical.
@smatthews1999 I think you might be misunderstood. Action can still pass data through payload. You just need to inherit Action interface and use it instead of default Action interface.
Yes I am. Thanks. Some real world code would be super... instead of the old INCREMENT example.
Agreed. I also think it should be up to the library maintainers to provide the documentation explaining the breaking changes as opposed to depending on pull requests from devs.
This is how we've been using ngrx v4 since it was in beta.
I created a sample crud app to share: https://github.com/loiane/angular-ngrx4-example
Our code structure is a little bit different from the ngrx sample app, but we liked working this way, with store modules.
Also appreciate any feedback if you see anything we might improve as well. :)
I'm also working on a vscode extension to generate the root and feature store directories automatically.
just take a look at the example here in the repo @smatthews1999 https://github.com/ngrx/platform/blob/master/example-app/app/books/actions/book.ts
i have an issue with using ngrx4 when i have working with less version of ngrx then work properly. how to resolve the issue related to : Object literal may only specify known properties, and 'payload' does not exist in type 'Action'.

Most helpful comment
This is how we've been using ngrx v4 since it was in beta.
I created a sample crud app to share: https://github.com/loiane/angular-ngrx4-example
Our code structure is a little bit different from the ngrx sample app, but we liked working this way, with
storemodules.Also appreciate any feedback if you see anything we might improve as well. :)
I'm also working on a vscode extension to generate the root and feature store directories automatically.