当 ngrx 存储状态包含 Map 时,为什么无法识别对此 Map 的更改?

2024-02-01

我根据他们的示例应用程序迁移到 Ngrx Store v4.1.1 (+ Angular5)。一切都像以前一样运行良好,但有一个 SubStore。该 SubStore 的状态包含一个已更改的 Map。但对这张地图的更改不知何故无法被识别。

工作中的 Plunker 可以在这里找到:https://plnkr.co/edit/2Z77Cq?p=preview https://plnkr.co/edit/2Z77Cq?p=preview详细代码如下

我的 NgModule 看起来像这样:

import {reducers} from './reducers';

@NgModule({
   imports: [ 
     BrowserModule,
     StoreModule.forRoot(reducers) 
   ],
   declarations: [ App ],
   bootstrap: [ App ],
   providers: [Service]
})

我的减速机看起来像这样:

import {
  ActionReducerMap,
  createSelector,
  createFeatureSelector,
} from '@ngrx/store';

import * as character from './character.reducer';

export interface State {
  character: character.State;
}

export const reducers: ActionReducerMap<State> = {
  character: character.reducer,
};

/** Character **/
export const getCharacterState = createFeatureSelector<character.State>('character');

export const getCharacter = createSelector(
  getCharacterState,
  character.getCharacter
);

SubStoreReducer包含以下代码:

import { Character, Item } from './models';
import * as character from './character';

export interface State {
  character: Character;
}

export const initialState: State = {
  character: null,
};

export function reducer(state = initialState, action:character.Actions): State {
  switch (action.type) {
    case character.INIT_CHARACTER:
      const char: Character = action.payload;
      state.character = char;
      console.log('init char', char);
      return Object.assign({}, state);

    case character.EQUIP_ITEM:
      const eqItem: Item = action.payload;
      state.character.wardrobeItemIds.set(eqItem.part, eqItem.id);
      console.log('eq ITEMMM', eqItem, state.character.wardrobeItemIds);
      return Object.assign({}, state);

    default:
      return state;
  }
}

export const getCharacter = (state: State) => state.character;

相应的操作是:

import { Action } from '@ngrx/store';
import { Character, Item } from './models';

export const INIT_CHARACTER = '[Character] Initialized Character';
export const EQUIP_ITEM = '[Character] Equipped Item';

export class InitCharacter implements Action {
  readonly type = INIT_CHARACTER;
  constructor(public payload: Character) {}
}

export class EqItem implements Action {
  readonly type = EQUIP_ITEM;
  constructor(public payload: Item) {}
}

export type Actions =
  InitCharacter |
  EqItem;

现在我在服务中使用新角色初始化 SubStore:

import { Injectable } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs/Observable';
import {Character, Item} from './models';

import * as fromRoot from './reducers.ts';
import * as CharacterAction from './character.ts';

@Injectable()
export class Service {
  character$: Observable<Character>;

  constructor(
    private store: Store<fromRoot.State>
  ) {
    // listen to the store
    this.character$ = this.store.select(fromRoot.getCharacter);

    this.character$.subscribe(
      (state: any) => console.log('char store triggered. State:', state)
    );

    // init the wardrobeItemIds Map
    const wardrobeItemIds = new Map<string, string>();
    wardrobeItemIds.set('part1', 'anyId');

    // init the character (this is just a dummy)
    let newCharacter: Character = {
      baseType: 'anyString',
      skinItemIds: [
        'string1',
        'string2'
      ],
      wardrobeItemIds: wardrobeItemIds
    }
    this.store.dispatch(new CharacterAction.InitCharacter(newCharacter));
  }

  addItem(part: string): void {
    // add rnd item of given part
    const item: EquipItem = {
      id: Math.random().toString(),
      part: part,
    }
    this.store.dispatch(new CharacterAction.EqItem(item));
  }
} 

这会导致我的订阅位于同一服务内

this.character$.subscribe(
  (state: any) => console.log('char store triggered. State:', state)
);

记录字符,这很好,因为它从 null 更改为字符对象。

现在如果我打电话addItem()哪个调用this.store.dispatch(new CharacterAction.EqItem(item));应该将一个项目添加到地图中state.character.wardrobeItemIds.

这应该会导致 Store Observable 再次触发,并且订阅应该记录更改的字符。但不知何故什么也没发生。 已经检查减速器是否正确接收操作。

不确定这只是我的愚蠢还是某种错误?

提前谢谢 飞鸟


看来 @ngrx/entity 是商店中更复杂数据结构的预期解决方案。如果您打开 Map,它们的使用将触发新的运行时检查,因为它们既不是不可变的也不是可序列化的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当 ngrx 存储状态包含 Map 时,为什么无法识别对此 Map 的更改? 的相关文章

  • 模拟 ngrx 在单元测试中存储带有参数的选择器(Angular)

    我正在尝试为 Angular 中的服务编写单元测试 我想模拟 ngrx 的 store select 函数 这样我就可以测试服务如何对存储选择器返回的不同值做出反应 我希望能够单独模拟每个选择器 我的主要问题是如何模拟参数化选择器 我之前使
  • TypeScript 类型不适用于扩展运算符

    我有一个 redux 风格的减速器 我正在使用 ngrx 它返回特定类型 当我在返回对象中使用展开运算符时 打字稿 linter 不会捕获无效属性 这是我的界面 interface MyState firstName string last
  • 使用ngrx一次获取store的当前状态

    您好 我想知道是否有人知道如何在无需订阅的情况下获取商店的当前状态 我目前正在使用 ngrx 订阅商店并访问其状态以设置组件的属性 但由于我订阅了该属性 所以它会不断刷新 因此 我正在寻找一种仅获取此属性一次的方法 以便我可以显示数据而无需
  • 为什么action第二次运行时没有触发Effect?

    Effect Effect loadDocsEffect this actions pipe ofType myActionTypes LoadDocs mergeMap action gt this myService getDocs m
  • 是否有可能在 ngrx-effects 内部抛出错误而不完成 Observable 流?

    有什么办法可以使用吗throw在 ngrx effects 流内有一个 Error 对象而没有完成流 我读过这些关于为什么流被抛出错误而被终止的很好的答案 ngrx 效果不会第二次运行 ngrx 影响错误处理 https github co
  • 对 NgRx 效果进行单元测试以确保服务方法被调用 - 不起作用

    我正在使用 NgRx 7 0 0 版本 这是我的 NgRx 效果类 import Injectable from angular core import ApisService from apis service import Effect
  • 无法从 ngrx/store 取消订阅 ActionsSubject

    I use ngrx store实现从订阅商店获取日期的登录操作 登录组件是模态的 当我输入错误的密码时 我得到data type LOGIN FAILED 但是 当我关闭模式并重新打开它时 数据操作仍然是LOGIN FAILED代替INI
  • 如何在 Rxjs 6 中测试 ngrx 管道选择

    以前我可以测试以下商店选择 this store select fromRoot someselector pipe map r gt this store dispatch new Action 这是我的测试中的 provide Stor
  • ngrx - 有条件地停止/删除效果/操作

    我目前正在使用 Ionic2 和 ngrx 构建一个应用程序 如果没有网络连接 我会尝试停止某些操作 通过停止 我的意思是以某种方式使它们对其他效果和商店不可见 或阻止它们进一步 传播 有没有办法做这样的事情 Effect checkNet
  • 在 NGRX 上的 ActionsSubject 订阅上使用操作的有效负载

    我又旧又坏Property payload does not exist on type Action执行此操作订阅 由于是创建操作 我需要有效负载来签出userId最近创建的用户并导航到 users userId 顺便说一句 我正在关注这
  • 为什么在 Http 服务中使用 .takeUntil() 而不是 .take(1)?

    Context 我正在努力实施 ngrx 效果 https github com ngrx effects在一个 ngrx 商店 https github com ngrx store项目并研究示例应用程序 https github com
  • 如何取消 RXJS Effects 中发出的角度 http 请求

    我想取消 Angular 8 中 RXJS 效果中发出的 http 请求 Effect getReport this action pipe ofType ActionTypes GET WIDGET map toPayload merge
  • ngrx/store 不显示表单的更新值

    我需要通过表单输入 2 个输入值 以兆字节为单位显示存储空间的使用情况 已使用空间和剩余空间 并显示来自 ngrx Store 的输入值 每次提交表单时 都会显示新值并更新旧值 问题是 UI 始终显示 used space 和剩余空间 的默
  • NGRX - 如何计算商店中商品的属性

    我们在 Angular 应用程序中使用 NGRX 数据来自 API 某些属性以未格式化的字符串形式来自 API 因此我们需要对其进行格式化 当然 这可以在 HTML 中完成 但问题是在 HTML 和 TypeScript 中的多个位置都需要
  • 从 Firebase Promise 分派操作后,ngrx 商店不更新 UI

    我正在尝试使用 Angular 4 开发一个基本的 NativeScript 应用程序 我还使用 ngrx 存储和 firebase 作为实时数据库 当我使用示例数组并更新存储而不与 firebase 集成时 程序工作正常 UI 也得到更新
  • 从组件 ngrx 更改存储状态

    我正在使用选择器从商店中进行选择 this quizz this store select getSelectedQuizz 我使用异步管道从模板中的可观察对象中读取数据 ngIf quizz async let quizz 我只定义了操作
  • @ngrx/store 是可观察到的热还是冷?

    我认为它是一个冷可观察的对象 默认情况下 但在代码或文档中找不到对它的引用 抱歉 如果已经问过这个问题 找不到东西 TLDR这是一个热门的观察点 因为动作主题 https github com ngrx platform blob mast
  • 在库中使用 ngrx 时如何避免调用 StoreModule.forRoot() 两次

    我正在创建一个使用 ngrx 的角度库 对于该库 我只有几个功能缩减器 我可以在库基础模块中轻松初始化它们 问题是我不知道是否在库基础模块中调用 StoreModule forRoot 该库的一些使用者已经使用了 ngrx 所以如果我这样做
  • 状态更改时不调用 ngrx 存储订阅

    我正在使用我的服务中定义的虚拟数据创建一个应用程序 在一个组件中 我具有以下删除产品的功能 removeItem productId string this cartService removeItem productId 以及服务如下 r
  • 如何在 ngrx/effects 中执行 if/else 操作?

    我正在使用 ngrx effects 我想根据以下情况分派不同的操作foo商店里的状态 这就是我现在正在做的 Effect foo1 this updates whenAction Actions FOO filter obj gt obj

随机推荐