gWombat
gWombat

Reputation: 517

Cannot load and display items from the store using ngrx and Angular

I trying to implement a store using Angular and ngrx and I have some problems to load values stored in the store. My items are loaded using a service and it seems to work properly.

Here is my code:

// app.module.ts
StoreModule.forRoot({
  todoReducer
}

// --------------------------
//todo.reducer.ts
export function todoReducer(state: TodoState, action: Action) {
  return reducer(state, action);
}

const reducer = createReducer(
  initialState,
  on(TodoActions.BEGIN_GET_TODOS, state => state),
  on(TodoActions.SUCCESS_GET_TODOS, (state: TodoState, {payload}) => {
    return {
      ...state,
      todos: payload,
      selectedTodo: null
    };
  }),
...

// --------------------------
// todo.effects.ts
getTodos$: Observable<Action> = createEffect(() =>
    this.$action.pipe(
      ofType(TodoActions.BEGIN_GET_TODOS),
      mergeMap(() =>
        this.todoService.getTodos().pipe(
          // Success http call
          map((data: Todo[]) =>
            TodoActions.SUCCESS_GET_TODOS({payload: data}),
          ),
          // Error http call
          catchError((error: Error) =>
            of(TodoActions.ERROR_TODOS(error)),
          ),
        )
      )
    )
);

// --------------------------
// todo-list.component.ts
export class TodoListComponent implements OnInit {
    todos: Observable<Array<Todo>>;
    
    ngOnInit(): void {
        this.todos = this.store.select(state => state.todos);
        this.store.dispatch(TodoActions.BEGIN_GET_TODOS());
      }
}

// --------------------------
// todo-list.component.html
<tr *ngFor="let todo of todos | async" (click)="onSelect(todo)">

My problem is that when the service loads all the todos, my component seems to not be updated. I always have an empty list of items in the html. But in the log I can see that the service properly retrieves my items from backend...

I'm certainly doing something wrong, but I don't know what. Any suggestions?

PS: I'm on Angular 8.2.12 and ngrx 8.6.0

Upvotes: 1

Views: 237

Answers (1)

Michael Kang
Michael Kang

Reputation: 52867

You need to pass an ActionReducerMap to StoreModule.forRoot().

StoreModule.forRoot({ 'todoState', todoReducer });

Make sure your state is initialized:

const initialState = { todos:[], selectedTodo: null };

Selecting Slices of State

Your selector should start from the root and include the state:

this.todos = this.store.select(state => state.todoState.todos);

Or even better, you should be using Selectors:

export const selectAll = createSelector<any, any, any>(state => state.todoState, todoState => todoState.todos);

Which you can use like this:

this.store.select(selectAll);

Upvotes: 0

Related Questions