Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ngrx/store not showing the updated values of a form

I need to enter 2 input values that shows the Usage of a storage space in megabytes (used_space and remaining_space) via a form and show the entered values from ngrx/Store. Each time the form is submitted the new values are showed and the old ones are updated. The problem is that the UI shows always the default values of (used_space and remaining_space) and I do not know if my architecture is right since I am new in ngrx/store.

Model (usage.model.ts):

   export interface Usage {
      used_space: number;
      remaining_space: number;
    }

Actions (usage.actions.ts):

export const EDIT_USAGE  = '[Usage] Edit';
...
export class EditUsage implements Action {
  readonly type = EDIT_USAGE
  constructor(public payload: Usage) {}
}
...
export type All = Reset | EditUsage;

Reducer (usage.reducer.ts): export type Action = UsageActions.All;

/// Default app state
const defaultState: Usage = {
  used_space: 2,
  remaining_space: 3
}

/// Helper function to create new state object
const newState = (state, newData) => {
  return Object.assign({}, state, newData)
}

export function usageReducer(state: Usage = defaultState, action: Action) {
  switch(action.type) {
    case UsageActions.EDIT_USAGE:
      // return [...state, action.payload];
      return newState(state, { Usage: action.payload });
    case UsageActions.RESET:
      return defaultState;
    default:
      return state;
  }
}

In app.component.ts:

  usage: Observable<Usage>

  constructor(private store: Store<AppState>) {
    this.usage = this.store.select('usage')
  }

  editUsage(used_space,remaining_space) {
    this.store.dispatch(new UsageActions.EditUsage({used_space:used_space , remaining_space:remaining_space}) )
  }

In app.component.html:

<input type="text"  #used_space>
<input type="text"  #remaining_space>
<button (click)="editUsage(used_space.value,remaining_space.value)" >Edit Space</button>

<div *ngIf="usage | async as u">
  <h2>Used space: {{ u.used_space }}</h2>
  <h2>remaining space: {{ u.remaining_space }}</h2>
</div>

I am not seeing any result and I do not know what is wrong.

like image 785
Tigris Laesus Avatar asked Oct 17 '22 17:10

Tigris Laesus


1 Answers

The problem lies in your reducer:

switch(action.type) {
  case UsageActions.EDIT_USAGE:
    return newState(state, { Usage: action.payload }); <<--------
}

you are passing previous state and a new object with usage as a property. What Object.assign does is: create a new object, append previous state to it, attach a brand new property Usage and add new values of store to that. Here's view of newly created object:

You can solve this passing the payload directly:

switch(action.type) {
  case UsageActions.EDIT_USAGE:
    return newState(state, action.payload);
}

Working Demo

Plus, as long as you are updating object as whole in your reducer, I believe you don't need Object.assign() too. You can directly return the action.payload as it is the new state.

like image 193
Syed Ali Taqi Avatar answered Nov 15 '22 10:11

Syed Ali Taqi