Skip to content
This repository has been archived by the owner on Jan 10, 2018. It is now read-only.

Store : Using select without subscribe #292

Closed
NicolasBouhours opened this issue Dec 11, 2016 · 14 comments
Closed

Store : Using select without subscribe #292

NicolasBouhours opened this issue Dec 11, 2016 · 14 comments
Labels

Comments

@NicolasBouhours
Copy link

Hi

I'm pretty young to angular 2 and nrgx,
So i'm creating my own mean-stack and i think about using nrgx state.
I follow basic introduction setup with counter reducer and i got one problem.

I write same code than in tutorial and i've this error : "{type: {} is not assignable to type number}

test

I will need for each select subscribe to the value and attach it manually or there a a more convient way to doing this using (store.select) and (Obersable) ?
I prefer ask for using good practices at beginning

Thank's ! :)

@fxck
Copy link

fxck commented Dec 11, 2016

async pipe in template

@NicolasBouhours
Copy link
Author

NicolasBouhours commented Dec 11, 2016

@fxck Thank's, what did you think, the best way is to use async on template or subscribe (like in my code with counterWorking) ?

@fxck
Copy link

fxck commented Dec 11, 2016

async pipe is almost always the better option, as it takes care of cleaning up(unsubscribing) for you

@kylecordes
Copy link
Contributor

For our projects here (and/or teaching) we recommend using the async pipe in nearly every possible case, and only manually subscribing to an observable when no better solution can be found. This turns out to be not very often.

However, for the type error the original poster reported, the actual solution is to stop using the "string parameter" form of the select operator and instead use the function parameter style.

this.counter = store.select(state => state.counter);

Some people prefer the string form (I don't recommend it all myself). If you prefer the string form and also don't want type errors you need to cast the results of the select call.

@afontaine
Copy link

afontaine commented Dec 20, 2016

Store#select is actually a generic function, so to fix the type error above and use the string form it would be called like this:

this.counter = store.select<number>('counter');

EDIT: The type definition can be found here

@MikeRyanDev
Copy link
Member

The typings for the string overload select will be improved in v3.0.0

@maxime1992
Copy link

@kylecordes

For our projects here (and/or teaching) we recommend using the async pipe in nearly every possible case

I'm interested in that solution but there's something I'm missing here :
So let say you have a userReducer with a default state :

{
  id: 1,
  name: 'Titi TOTO',
  username: 'Tito',
  age: 100,
  gender: 'male'
}

And you want to display them all. Will you use that async pipe on every display like that ?

<ul>
  <li>{{ (user | async).id }}</li>
  <li>{{ (user | async).name }}</li>
  <li>{{ (user | async).username }}</li>
  <li>{{ (user | async).age }}</li>
  <li>{{ (user | async).gender }}</li>
</ul>

Of course, we might create a component and pass the user object with the async pipe to get rid of asynchrounous code. But in that case how would you do it ? Manually subscribe ? Async everywhere ? Anything else ?

@kylecordes
Copy link
Contributor

Typically we handle the situation by creating an outer ("smart") component which obtains the data and observable form, then in that outer component we use the async pipe to pass the actual data to an inner ("view") component which would contain the snippet of template shown above. This is called variously the smart/view component pattern, as well as many other names. It is pervasive among redux/react users, and popular among complex observable state Angular users.

I realize this is a 46 minute answer to a three minute question, but you can see a whole bunch more I have to say about this in the following video of a talk I gave a couple months ago.

https://www.youtube.com/watch?v=eBLTz8QRg4Q

@aitboudad
Copy link

in angular 4 your can use:

<ul *ngIf="user$|async as user">
  <li>{{ user.id }}</li>
  <li>{{ user.name }}</li>
  <li>{{ user.username }}</li>
  <li>{{ user.age }}</li>
  <li>{{ user.gender }}</li>
</ul>

@kylecordes
Copy link
Contributor

@aitboudad With the shipped rc.3 it has to be:

*ngIf="user$|async ; let user"

The improvement you show above, is in master (a couple days ago, to much appreciation...) but hasn't shipped in an RC yet.

@ksimonson10
Copy link

ksimonson10 commented Apr 11, 2017

So, now with the option to use:

<ul *ngIf="user$|async as user">
  <li>{{ user.id }}</li>
  <li>{{ user.name }}</li>
  <li>{{ user.username }}</li>
  <li>{{ user.age }}</li>
  <li>{{ user.gender }}</li>
</ul>

What would be the benefits to using that over the smart/view component pattern? Or visa versa?

@maxime1992
Copy link

maxime1992 commented Apr 11, 2017

@ksimonson10 you should always use smart/dumb components as much as possible. In few cases, you don't need a dumb component to display only few values. This is where you should use ngIf.

But for example if this is in a for loop, you might want to use a dumb component and optimize perfs with the changeDetectionStrategy set to OnPush (if you have immutable data).

gmarler added a commit to gmarler/ngrx-course that referenced this issue Apr 28, 2017
@jek-bao-choo
Copy link

@kylecordes @aitboudad Speaking of using *ngIf="user$|async ; let user" or <ul *ngIf="user$|async as user">, I tried using .share() operator but apparently it is not working. For example having this.counter$ = this.store.select('counter').share(); while doing multiple counter$ | async in the component.html this creates multiple subscriptions.

Correct me if I am wrong about the above, but is there a reason why it is creating multiple subscriptions even with the use of share() operator or publish().refCount() operators?

@robwormald
Copy link
Contributor

Please check this against NgRx v4, and if it’s still an issue, please reopen on https://github.com/ngrx/platform. Thanks!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

10 participants