简体   繁体   English

订阅NgRx存储将返回空对象

[英]Subscription to the NgRx store returns empty object

I am trying to develop aa simple angular app using NgRx to maintain state. 我正在尝试使用NgRx开发一个简单的角度应用程序以维持状态。

Unfortunately, the callback to the subscription to the store gets fired but always returns an empty object. 不幸的是,对商店订阅的回调被触发,但始终返回一个空对象。

I am trying to dispatch the object to store as 我正在尝试调度对象以存储为

this._store.dispatch({
  type: 'ShowPassword',
  payload: value
})

and a look at the reducer function 看一下reduce函数

export function showPasswordReducer(state, action) {
  //console.log(state);
    switch (action.type) {

    case 'ShowPassword':
      return {
        ...state,
        'ShowPassword': action.payload
      }
    break;
    default:
        return state;
    }
}

I am adding the reference of StoreModule in the imports array of root module as 我在根模块的imports数组中添加StoreModule的引用为

StoreModule.forRoot(showPasswordReducer)

and subscribing to the store as 并以以下方式订阅商店

this._store.subscribe(val => {
    if (val)
        this.showPassword = val.ShowPassword;
})

Stackblitz link: https://stackblitz.com/edit/angular-first-ngrx-demo Stackblitz链接: https ://stackblitz.com/edit/angular-first-ngrx-demo

There are a couple of basic NGRX pieces missing in your code - 您的代码中缺少一些基本的NGRX片段-

Let's deal with them one by one: 让我们一一处理它们:

a) You must have an initial state [I am assuming that you want to have a state which tracks a boolean called showPassword ]. a)您必须具有一个初始状态[我假设您要具有一个跟踪名为showPassword的布尔值的状态]。 Define an initial state object like this: 定义一个初始状态对象,如下所示:

export const initialState = {
  showPassword: false
};

b) Setup your reducer to make use of initial state like this: b)设置减速器以利用如下初始状态:

export function showPasswordReducer(state = initialState, action) {
  //console.log(state);
  switch (action.type) {
    case 'ShowPassword':
      return {showPassword: action.payload};
      break;
    default:
      return state;
  }
}

Notice that in case of default action reducer will return the initial state. 请注意,在默认操作下,reducer将返回初始状态。

c) Now inject the reducer in forRoot method with the state name like this: c)现在,在forRoot方法中以如下状态名称注入reducer:

@NgModule({
  imports: [BrowserModule, FormsModule, StoreModule.forRoot({ShowPassword: showPasswordReducer})],
  declarations: [AppComponent],
  bootstrap: [AppComponent]
})

d) Now subscribe to the store [ Ideally You MUST have selectors to get the piece of information from the store but to keep things simple, simply subscribe to the store directly and look for the same property which was used in the forRoot like this: d)现在订阅商店[ 理想情况下,您必须具有选择器来从商店中获取信息,但为了简单forRoot ,只需直接订阅商店,并查找在forRoot中使用的相同属性,如下所示:

ngOnInit() {
    this._store.subscribe(val => {
      console.log(val);
      if (val)
        this.showPassword = val.ShowPassword.showPassword;
    })
  }

Working stackblitz - https://stackblitz.com/edit/angular-first-ngrx-demo-7yrl2r?file=src/app/app.module.ts 工作stackblitz- https: //stackblitz.com/edit/angular-first-ngrx-demo-7yrl2r ? file = src/app/app.module.ts

Hope it helps. 希望能帮助到你。

You are using ngrx 8, so you should embrace that syntax, which is also cleaner in my opinion. 您正在使用ngrx 8,因此您应该采用该语法,我认为这也更干净。 We now have access to createReducer and createAction . 现在,我们可以访问createReducercreateAction So I suggest the following: 所以我建议如下:

import { createAction, createReducer, on, } from '@ngrx/store';

export const showPwd = createAction(
  'Show Password',
  ({ showPw }: { showPw: boolean }) => ({
    showPw,
  })
)

const initialState = {
  showPw: false
};

export const showPasswordReducer = createReducer(
  initialState.showPw,
    // here you would probably want to have the action(s) in a separate file
    on(this.showPwd, (state: any, action: any) => {
    return action.showPw;
  }),
)

export function reducer(state: any | undefined, action: any) {
  return showPasswordReducer(state, action);
}

Then remember to mark to app.module imports : 然后记住标记为app.module imports

StoreModule.forRoot({showPwd: showPasswordReducer})

Then finally in the component where you dispatch the action and listen to store: 然后最后在您分派操作并监听存储的组件中:

ngOnInit() {
  this._store.subscribe(val => {
    if (val && val.showPwd)
      this.showPassword = val.showPwd;
  })
}

ToggleCheckbox(value: boolean) {
  this._store.dispatch(showPwd({showPw: value}))
}

Your forked STACKBLITZ 您的分叉STACKBLITZ

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM