NgRx createReducer() 和 on() 给出错误

Posted

技术标签:

【中文标题】NgRx createReducer() 和 on() 给出错误【英文标题】:NgRx createReducer() and on() is giving error 【发布时间】:2021-05-24 09:47:06 【问题描述】:

我是新人。到 NgRx。

当我尝试使用 createReducer() 创建减速器时,我收到错误 Expected 4 arguments, but got 2. 当我尝试将第 3 和第 4 个参数作为 null 传递时,出现错误

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)

reducer 代码

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
  )
);

动作代码

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>()
);

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 

package.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"
  

【问题讨论】:

【参考方案1】:

我在我的 IDE 中看到了这个错误,以及与 @ngrx/store 相关的其他一些奇怪的类型相关错误,但项目编译得很好。

我已将我的项目中使用 @ngrx 的 typescript 版本升级到最新版本(当时是 v4.3.4),但我的工作区包括其他几个项目,我的 IDE(我正在使用 WebStorm)typescript 语言服务是配置为使用安装在我的其他项目之一上的旧版打字稿。将 IDE typescript 服务配置为使用较新的 typescript 版本后,错误就消失了。

所以在我的情况下,这是几件不同的事情 - 首先,我需要为使用 @ngrx 的项目升级 typescript 版本,以便与一些更新的项目一起工作@ngrx 正在使用的语言功能。然后,我还必须确保我的 IDE 的打字稿语言服务正在使用该版本,或者至少是相当新的打字稿版本,以避免在编辑器窗口中看到虚假错误.

【讨论】:

【参考方案2】:

确保您的@ngrx/store 库版本和您安装的@angular/core 版本不匹配。

通常它们应该使用相同的主要版本 - 对于@angular/core ^9.x.x,您应该使用相应的 ^9.x.x 版本的@ngrx/store。这发生在我使用 Angular 9 并安装最新、稳定的 ngrx 版本(目前是 11.x.x)时。

阅读有关要求的更多信息(链接参考 V9,但也可以申请更新的):https://ngrx.io/guide/migration/v9

【讨论】:

【参考方案3】:

你的动作和减速器看起来很奇怪。根据文档,它应该是这样的:

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 ;
    
  )
);

或者,如果您更喜欢简写:

// equal shorthand function
export const shoppingListReducer = createReducer(
  initialState,
  on(
    AddIngredient, // the action, not the action.type
    (state,  ingredient ) => (ingredients: [...state.ingredients, ingredient])
  )
);

主要有以下几点:

(state: any,  updatedValue : any) => ( ...state, prop: updatedValue )
需要一个带有名为 updatedValue 的道具的动作(与动作相比,道具现在命名为成分) 返回一个从当前状态组装的对象和一个名为 prop (*) 的字段

(*) 如果这行得通,它会导致类似的状态

interface MyAccidentalState 
  ingredients: Array<Ingredient>;
  prop: Ingredient;

...但它不起作用,因为您的操作没有命名道具“updatedValue”并且prop: updatedValue 不是prop: updatedValue

并且因为它没有命名的 prop 'updatedValue',编译器在对象解构部分爆炸

(state: any, updatedValue : any) =&gt; ...

(state: any, updatedValue : any) =&gt; ... 中的任何类型可能会否认编译器已经存在的一些知识:updatedValue 旨在成为一种成分,而 state 是(现在)一个 MyState。

旁注:

保持集合的状态是 ngrx/entity 可能有用的东西 - 但你的方式也是有效的。

【讨论】:

此代码对我不起作用 - 出现与 OP 相同的错误

以上是关于NgRx createReducer() 和 on() 给出错误的主要内容,如果未能解决你的问题,请参考以下文章

javascript createReducer.js

带有 PWA 和 Service Worker 的 NGRX 离线缓存

ngrx 调度的动作未达到效果

ngrx 和 ngxs 之间的性能差异? [关闭]

Angular 7、Ngrx、Rxjs 6 - 访问延迟加载模块之间的状态

在调度一个动作和 NgRx 效果之前执行多个 API 调用