5

some searching on SO leaves me to believe that there is no good (simple) way of achieving the question in the title. The following threads are all very related:

Get current state in ngrx

Getting current state in ngrx

Get current ngrx state without subscribe

Using ngrx to obtain store's current state once

How to get current value of State object with @ngrx/store?

From the last thread ^, it seems that the only way of achieving this is to use withLatestFrom() or combineLatest().

It can't be the case that the following is the only way to make sure you only receive 1 item and that this item is the most recent one:

of('terribleLatestValueHack').pipe(
  withLatestFrom(this.store.select(itemSelector))
  ).subscribe((stringAndItem: [string, Item]) => {
    const [, item] = stringAndItem;
    // do something with item
});

Given that selecting one most recent item from a Store

  • is a (very) simple use-case
  • seems to be a highly requested functionality

I would really like to know why the existing support (apparently there was - in NGRX v2 - according to How to get current value of State object with @ngrx/store?) for it has been removed.

Michahell
  • 4,905
  • 5
  • 29
  • 45

1 Answers1

5

I forgot to add that I was of the impression that store.select(...).pipe(first()) does not return the most recent item from the store. But it seems it does and the cause for any faulty values it returns lies in our own code.

store.select(...).pipe(first()) indeed just does that: return one current item from a Store (and complete the Observable).

Michahell
  • 4,905
  • 5
  • 29
  • 45
  • 1
    Glad I could help ;-) – ggradnig Jul 30 '18 at 15:54
  • 1
    I believe the ngrx documentation also states that it guarantees to return synchronously if you take(1) or first() the observable from the select. Which can be very useful indeed. – Mark Hughes Jul 30 '18 at 18:14
  • Do you have the link for the documentation where this is said? – René Winkler Jul 30 '18 at 18:19
  • It was in the change log for ngrx store v1 to v2, when they removed the .value accessor to get the current state - see the quote in the last update to this answer https://stackoverflow.com/a/35635130/789529 - the original doc seems to have been removed and I can't find it any more :( – Mark Hughes Jul 31 '18 at 10:42
  • 1
    Essentially @RenéWinkler the store is an extension of BehaviourSubject, and a BehaviourSubject will fire a subscription synchronously with the current value (assuming there IS a current value). Therefore, by filtering with take(1) or first() you'll get just a single snapshot of the current value synchronously. – Mark Hughes Jul 31 '18 at 10:55
  • @MarkHughes I read something similar. But I find this a curious choice, as you won't know if you won't read this somewhere, and using the same syntax as other operators will let you think it's asynchronous. A specific method indicating a synchronous nature would at least be a lot more clear.. – Michahell Aug 01 '18 at 08:54
  • 1
    I believe the principle that the authors of NgRX are following is "make your code as if everything is asynchronous, and react to the events that happen". So they really are trying to encourage you NOT to ever look at the "current" state. I'm not sure I really agree with this, because sometimes you just need the current value now. I've wrapped our state service in a bunch of classes which have methods like "getXCurrent()" which do, essentially, `let a = null; this.store.select(x => x.y).pipe(take(1)).subscribe((y) => a = y); return a;` - which will return null or current value if there is one. – Mark Hughes Aug 01 '18 at 09:05
  • ... But, we only have those where there is a clear need to get the current value of something without any view to the future or past. Mostly, we react to long-lived select-derived observables, in the proper "ngrx" way. @MichaelTrouw – Mark Hughes Aug 01 '18 at 09:06
  • Yes, our use case is exactly the same. I like the synchronous wrapper function! – Michahell Aug 01 '18 at 11:12
  • It's nice - just be careful not to overuse it @MichaelTrouw ;) – Mark Hughes Aug 01 '18 at 13:53