angular - Egenskaben 'payload' findes ikke på typen 'Action', når man opgraderer @ngrx/Store
Jeg har @ngrx/store-pakken i min Angular (4.x) app, og opgraderer fra v2.2.2 -> v4.0.0. Jeg kan se, at migrationsnoterne siger:
Payload-egenskaben er blevet fjernet fra Action-interface.
Dog virker det eksempel, de giver, helt kontraintuitivt (efter min mening...).
Jeg har en reducer-funktion, som ser sådan ud:
export function titleReducer(state = { company: 'MyCo', site: 'London' }, action: Action): ITitle {
switch (action.type) {
case 'SET_TITLE':
return {
company: action.payload.company,
site: action.payload.site,
department: action.payload.department,
line: action.payload.line
}
case 'RESET':
return {
company: 'MyCo',
site: 'London'
}
default:
return state
}
}
Hvilket som forventet nu udløser en TypeScript-fejl:
[ts] Egenskaben 'payload' findes ikke på typen 'Action'
Men jeg har ingen idé ud fra migrationsguiden, hvad dette skal ændres til. Nogle idéer?
Svar #1
Du kan oprette din egen handlingstype, der har en payload defineret, se eksempelappen som reference:
class AddBookAction implements Action {
readonly type = ADD_BOOK;
constructor(public payload: Book) {}
}
Brug derefter den type i reducerefunktionen:
function reducer(state = initialState, action: AddBookAction): State
Handling kunne udsendes sådan her:
this.store.dispatch(new AddBookAction(book));
Bemærk også, at eksempelappen kombinerer alle de handlingstyper, som en reducer kan udføre, i en enkelt unionstype:
export type Actions =
| AddBookAction
| AddBookSuccessAction
export function reducer(state = initialState, action: Actions): State
Svar #2
Ok, det er et meget interessant emne. Jeg gik glip af den nye udgivelse (4.0), men jeg opdaterede bibliotekerne i mit repo, og jeg så, at jeg har det samme problem.
Det er korrekt. Payload-attributten blev slettet fra Action i den nye udgivelse. Hvis du bruger effekter til at dispatch action, er løsningen simpel, og du kan læse om dem i migrationsnoterne
men hvis du vil have dispatch til at sende payload, kan du oprette en parametriseret Action på denne måde:
export interface ActionWithPayload<T> extends Action {
payload: T;
}
så hvis du tilføjede dette interface, kan du ændre reducer på denne måde:
export class SomeObject {
company: string;
site: string;
department: string;
line: string;
}
export function titleReducer(state = { company: 'MyCo', site: 'London' }, action: ActionWithPayload<SomeObject>): ITitle {
switch (action.type) {
case 'SET_TITLE':
return {
company: action.payload.company,
site: action.payload.site,
department: action.payload.department,
line: action.payload.line
}
...
Det er den bedste løsning, jeg har fundet. Jeg skal forstå bedre årsagen til denne ændring, og hvis jeg finder en bedre løsning, tilføjer jeg dem her.
