piy*_*ain 7 javascript ngrx angular ngrx-store
我是新的。到 NgRx。
当我尝试使用创建减速器createReducer()时出现错误Expected 4 arguments, but got 2.
当我尝试将第 3 和第 4 个参数作为空值传递时,出现错误
Argument of type '(state: any, { updatedValue }: any) => any' is not assignable to parameter of type 'readonly ActionCreator<string, FunctionWithParametersType<any[], object>>[]'.
Type '(state: any, { updatedValue }: any) => any' is missing the following properties from type 'readonly ActionCreator<string, FunctionWithParametersType<any[], object>>[]': concat, join, slice, indexOf, and 15 more.ts(2345)
Run Code Online (Sandbox Code Playgroud)
减速机代码
import { createReducer, on, State, Action } from '@ngrx/store';
import { Ingredient } from '../../shared/ingredient.model';
import * as ShoppingListAction from './shopping-list.action';
export const initialState = {
ingredients: [
new Ingredient('Apples', 5),
new Ingredient('Tomatoes', 10),
]
}
export const shoppingListReducer = createReducer(
initialState,
on(
'ADD_INGREDIENT',
(state: any, { updatedValue }: any) => ({ ...state, prop: updatedValue }),
null,
null
)
);
Run Code Online (Sandbox Code Playgroud)
动作代码
import { createAction, props } from '@ngrx/store';
import { Ingredient } from '../../shared/ingredient.model';
export const ADD_INGREDIENT = 'ADD_INGREDIENT';
export const AddIngredient = createAction(
ADD_INGREDIENT,
props<Ingredient>()
);
Run Code Online (Sandbox Code Playgroud)
app.module.ts
import { SharedModule } from './shared/shared.module';
import { CoreModule } from './core.module';
import { LoggingService } from './logging.service';
// Store
import { shoppingListReducer } from './shopping-list/store/shopping-list.reducer';
@NgModule({
declarations: [AppComponent, HeaderComponent],
imports: [
BrowserModule,
HttpClientModule,
AppRoutingModule,
SharedModule,
CoreModule,
StoreModule.forRoot({ 'slReduce': shoppingListReducer })
],
bootstrap: [AppComponent],
// providers: [LoggingService]
})
export class AppModule {}
Run Code Online (Sandbox Code Playgroud)
包.json
"dependencies": {
"@angular/animations": "^11.2.1",
"@angular/common": "^11.2.1",
"@angular/compiler": "^11.2.1",
"@angular/core": "^11.2.1",
"@angular/forms": "^11.2.1",
"@angular/platform-browser": "^11.2.1",
"@angular/platform-browser-dynamic": "^11.2.1",
"@angular/router": "^11.2.1",
"@ngrx/store": "^11.0.1",
"bootstrap": "3.3.7",
"core-js": "^3.1.2",
"rxjs": "^6.0.0",
"tslib": "^2.0.0",
"zone.js": "~0.11.3"
}
Run Code Online (Sandbox Code Playgroud)
Your action and your reducer look strange. According to the docs it should be something like:
export interface MyState {
ingredients: Array<Ingredient>;
}
export const initialState: MyState = {
ingredients: [
new Ingredient('Apples', 5),
new Ingredient('Tomatoes', 10),
]
}
// see https://ngrx.io/guide/store/actions
// note: the prop has a 'name: Type', not just 'Type'
export const AddIngredient = createAction(
ADD_INGREDIENT,
props<{ingredient: Ingredient}>()
);
// verbose func to show difference
export const shoppingListReducer = createReducer(
initialState,
on(
AddIngredient, // the action, not the action.type
(state, { ingredient }) => {
let ingredients = Array.from(state.ingredients);
ingredients.push(ingredient);
return { ingredients };
}
)
);
Run Code Online (Sandbox Code Playgroud)
Or if you prefer the shorthand:
// equal shorthand function
export const shoppingListReducer = createReducer(
initialState,
on(
AddIngredient, // the action, not the action.type
(state, { ingredient }) => ({ingredients: [...state.ingredients, ingredient]})
)
);
Run Code Online (Sandbox Code Playgroud)
The main points are:
(state: any, { updatedValue }: any) => ({ ...state, prop: updatedValue })
Run Code Online (Sandbox Code Playgroud)
(*) If this worked, it would lead to a state like
interface MyAccidentalState {
ingredients: Array<Ingredient>;
prop: Ingredient;
}
Run Code Online (Sandbox Code Playgroud)
... but it does not work, as your action has no named prop 'updatedValue' and prop: updatedValue was not {prop: updatedValue}.
And because it has no named prop 'updatedValue', the compiler explodes at the object destructuring part of
(state: any, { updatedValue }: any) => ...
And the any-typing in (state: any, { updatedValue }: any) => ... may deny the compiler some knowledge which was already there: updatedValue was intended to be an Ingredient, and state is (now) a MyState.
Side-note:
Keeping the state of a collection is something where ngrx/entity might be useful - but your way is valid, too.
| 归档时间: |
|
| 查看次数: |
1188 次 |
| 最近记录: |