【问题标题】:NgRx createReducer() and on() is giving errorNgRx createReducer() 和 on() 给出错误
【发布时间】: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"
  }

【问题讨论】:

    标签: javascript angular ngrx ngrx-store


    【解决方案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 相同的错误
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-11-21
        • 2021-05-20
        • 2011-12-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多