Search code examples
angularngrxngrx-store

How should I detect NGRX state event in a component?


I'm trying to make use of ngrx/store in an Angular app to remove lots of http requests that are currently happening and create an application state.

All libs should be up to date (within the last few weeks).

I have a contest-component that shows a contest. Another instance of the contest-component may change the contest and I want to reflect that in any other components that also show the same contest.

So if the contest gets changed in one component, I want that to be updated in the store and any other components that reference the contest should get the updated contest data.

What do I need in my component to subscribe to an event from the state (which I assume is what I need to do) to get the updated data (contest).

I plan to add an Effect later to manage the update to the backend, for now I'm just trying to get FE working, that's why it's not listed here.

At this point I;ve just been copying bits of code from tutorials, feel free to point out any other issues you spot (eg uneccessary code)

contest-action.ts

export enum ContestActionTypes {
 AddContest = '[Contest] Create Contest',
 UpdateContest = '[Contest] Update Contest',
}

export class CreateContest implements Action {
  readonly type = ContestActionTypes.AddContest;

  constructor(public payload: { contest: Contest }) {
  }
}

export class UpdateContest implements Action {
  readonly type = ContestActionTypes.UpdateContest;

  constructor(public payload: { contest: Contest }) {
  }
}

export type ContestActions =
  CreateContest
  | UpdateContest;

contest-reducer.ts

export interface ContestState extends EntityState<Contest> {
  allContestsLoaded: boolean;
}

export const adapter: EntityAdapter<Contest> =
  createEntityAdapter<Contest>({});


export const initialContestState: ContestState =
  adapter.getInitialState({
    allContestsLoaded: false
  });


export function contestReducer(state = initialContestState,
                               action: ContestActions): ContestState {
  switch (action.type) {
    case ContestActionTypes.AddContest: {
      return adapter.addOne(action.payload.contest, state);
    }
    case ContestActionTypes.UpdateContest: {
      console.log(`contestReducer.UpdateContest payload: ` + action.payload.contest);
      return adapter.updateOne(
        {id: action.payload.contest.id, changes: action.payload.contest},
                state);
    }
    default: {
      return state;
    }
  }

  return contestReducer(state, action);
}

contest-component.ts The saveContest() function is called correctly from another function when the html form is changed.

I'm guessing I'll need to add "something" to the ngOnInit() of the component to subscribe to and event emitted by the store? That something is what I need help with.

private saveContest(): void {
    this.store.dispatch(new UpdateContest({contest: this.contest}));

}

Solution

  • The store is reactive. If you change something in the store, all the subscribers get notified of this change. To read store data, you can use selectors.