BizzyBob
BizzyBob

Reputation: 14740

How to best subscribe to NGRX state change in view?

I'm brand new to ngrx and rxjs, so I think there's probably a simple solution for this that is not obvious to me yet :-)

I've got an ngrx store set up and working fine with the following state:

I've got actions and reducers set up working fine. When a user creates a new Message, I dispatch an action MessageCreated which results in a new message being added to my store (inside array property of Thread entity), which in turn updates my view. Hooray!

The observable for my Thread is working and now includes the new Message:

thread$ = store.pipe(select(selectThreadWithMessages(id));

My problem is I need a way to update a property on the newly created Message (isNew = true so an animation gets applied in view). But, I don't want to just apply this to all messages. I have it 'working' by simply applying it to the last Message in the array (which should always be the newest), but this doesn't feel like the "right" way to go.

What if I want to react to a newest item that comes in, when there isn't an easy way to know which one it is?

Here's what I've thought of doing:

Maybe initially subscribe to store to get initial data, and also have a stream of Messages that get added to the collection..? Seems like maybe that's sidestepping the purpose of the store to begin with...

Maybe break out Messages into their own feature state and have a separate selector for that? But maybe that doesn't really help with my original problem.

I guess what it comes down to in general is referencing an observable collection Message[] and correctly applying new individual instances Message that come along after the view loads.

I'm loving the idea of reactive programming, it just obviously not second-nature to me yet.

Any advice much appreciated..!

Upvotes: 1

Views: 946

Answers (1)

John
John

Reputation: 10009

Easiest solution might be to augment ThreadsState (Entity) to seperately store the "most recently created message". Then you could subscribe to that message and, when it changes, react appropriately.

If you are using ngrx effects, an alternative idea might be to inject the Actions stream into your component and subscribe to MessageCreated actions (looks like this would only work if the MessageCreated action's payload contained enough information to identify which message was created).

i.e.

constructor(
  private actions$: Actions,
) {}

ngOnInit() {
  this.subscriptions.push(
    this.actions$.pipe(ofType(MessageCreated)).subscribe(action => {
      // do stuff
    })
  )
}

ngOnDestroy() {
  this.subscriptions.forEach(sub => sub.unsubscribe())
}

Upvotes: 2

Related Questions