41

I'm new to Redux and started with ngrx. I'm unable to understand the meaning of this line of code store.select:

 clock: Observable<Date>;
 this.clock = store.select('clock');
Inego
  • 1,039
  • 1
  • 12
  • 19
blackHawk
  • 6,047
  • 13
  • 57
  • 100

4 Answers4

53

In very simple terms select gives you back a slice of data from the application state wrapped into an Observable.

What it means is, select operator gets the chunk of data you need and then it converts it into an Observable object. So, what you get back is an Observable that wraps the required data. To consume the data you need to subscribe to it.

Lets see a very basic example.

  1. Lets define the model of our store

    export interface AppStore {
       clock: Date
    }
    
  2. Import the Store into your component from '@ngrx/store'

  3. Create a store by injecting into the constructor

    constructor(private _store: Store<AppStore>){}
    
  4. Select returns an Observable.

    So, declare the clock variable in your component as follows:-

    public clock: Observable<Date>;
    

    Now you can do something like follows:-

    this.clock = this._store.select('clock');
    
Nicholas K
  • 15,148
  • 7
  • 31
  • 57
Mav55
  • 4,080
  • 2
  • 21
  • 20
  • Head Up for simple explanation – ismail baig Feb 28 '18 at 04:07
  • i tried this, i get an observable, and if i print it i get > Store {_isScalar: false, actionsObserver: ActionsSubject, reducerManager: ReducerManager, source: Store, operator: DistinctUntilChangedOperator} my data seems somewhere inside that observable, how do i get it from it? – Robdll Mar 01 '18 at 15:35
  • You need to subscribe to an observable and then you will the required data. – Mav55 Mar 01 '18 at 19:49
  • Kloop4: if you do not know what an obervable is, you need to look into RxJs. Please refer the official page here http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html – Mav55 Mar 01 '18 at 20:04
  • @Koop4 you need to use the async pipe – bertonc96 Jul 08 '19 at 13:49
  • bertonc96: async pipe is another way of subscribing to an observable. It depends what place you need to subscribe. async pipe is used in the html template. – Mav55 Jul 11 '19 at 21:19
23

Wow, this is a big topic. So basically "select" is really a RXJS operator that is used in this case to retrieve the value of a part of the application state object. So say your main app state has a array of users and a array of security functions. "Select" allows you to get a reference to a observable whose value is just that array of users. Before you get into ngrx you really need to study up on Observables and RXJS. I found this article linked off of the main Github project page for ngrx helpful.

https://gist.github.com/btroncone/a6e4347326749f938510

RXJS and redux can be a big topic but I suggest working on your knowledge in small bite size chunks. It took me about 2 months of working with it before I really started to feel comfortable. Even if you don't stay with ngrx, understanding how RXJS works is incredibly useful and is worth the time investment to learn it.

Here is a gist article that also gives a good intro into RXJS. https://gist.github.com/staltz/868e7e9bc2a7b8c1f754

wiredprogrammer
  • 545
  • 4
  • 13
  • Could you tell me how you took 2 months to get comfortable, i mean every developer needs such time, are you new bie, BTW nice answer – blackHawk Aug 13 '16 at 11:46
  • Also i red up about select, its like map operator, takes function and transform value, is it right? – blackHawk Aug 13 '16 at 11:48
  • 8
    I had a project I was working on that we were converting to Angular 2 and decided to give ngrx a go. I was new to ngrx and also to rxjs. I'd say I spent more time learning the concepts of rxjs and how observables work than ngrx. Most of what took time for me grasp with ngrx was what are the best conventions setting up reducers and the flow logic. How to set up action creators. I took heavy inspiration for the project set up from the example app linked off of the ngrx store project readme. https://github.com/ngrx/example-app – wiredprogrammer Aug 13 '16 at 12:22
  • Being able to understand what was going on in the example app took a bit of time. I also got a egghead subscription and watched redux videos made by the creator Dan Abrimov. Did some reading of popular questions on the redux project issues. – wiredprogrammer Aug 13 '16 at 12:24
  • I've been a programmer for about 15 years but I've only gotten into the JavaScript side of it in about the last 5 and only started learning about the frameworks in the last 2 or 3 years. I'm a bit late to the framework scene. – wiredprogrammer Aug 13 '16 at 12:36
  • The store version of the select operator I think is a bit more specialized but it has the same general function as the rxjs operator. According to the documentation it would seem select and map are aliases for each other. http://reactivex.io/documentation/operators/map.html – wiredprogrammer Aug 13 '16 at 12:45
  • can we have multiple reducers and stores, what I understood till now(1 day), that from component(for single value like todo) we have action that will dispatch with payload to the reducer then reducer has some logic based on type(it has return statement in each switch case, so when it return where it goes?) then we have a store(I dnt know where it is, its imported from node module) store would have some subject that could reflect changed value back to component – blackHawk Aug 13 '16 at 13:47
  • so can we have multiple stores and reducer, so i understand we can have multiple reducers, what about store, it seems that stores are designed to have single value, and for second value/property in component we will need another store, is it right? – blackHawk Aug 13 '16 at 13:50
  • ngrx and redux only allow one store since it is a centralized state. You can have multiple reducers which work on parts of the state. So in my previous example you'd have a reducer for the array of users and a different reducer for the array of security functions. Both act on the central store but affect only a slice of the store. All dispatches are run on both reducers but when a dispatch goes to a reducer that doesn't care about the action it should return the state by default. New values are emitted on the store only when the objects in the store are replaced with brand new objects. – wiredprogrammer Aug 13 '16 at 14:00
  • You'll notice in the examples they do most of their reducer returns using Object.Assign so they can create a brand new object but copy most of the values from the original state object. – wiredprogrammer Aug 13 '16 at 14:00
  • Most of this is covered in the gist I posted earlier but as far as where the return goes .. ngrx store creates a object and then creates properties on that object with the same names as the reducer object you pass into it. The store object is a observable ( I think). When a reducer is run and a value returned it assigns that value to the property on the object it created with the same name as the reducer. This is a bit low level but can help you general understanding of why and how things work. I really suggest going through that gist though. – wiredprogrammer Aug 13 '16 at 14:07
  • Ok I will, could you explain me whats going on here https://github.com/blackhawk389/learn-angular2 check out step 40 store state in the app folder – blackHawk Aug 13 '16 at 17:04
  • https://egghead.io/lessons/angular-2-ngrx-store-in-10-minutes This should give you a good basic overview. I'm not going to retread the basics in a comment thread. Sorry. – wiredprogrammer Aug 13 '16 at 20:16
  • some things need time, to settle in the mind. Rxjs is complex, not simple to take in. I agree with you. I also am at the beginning-medium amount of time, with rxjs, and I love it but still I need some time to settle it in the mind. – Vladimir Despotovic Mar 30 '22 at 14:58
3

It returns the state called 'clock'.

Here is an example. In the constructor store.select is called, this time with 'todos'.

https://github.com/btroncone/ngrx-examples/blob/master/todos/src/app/todo-app.ts

export class TodoApp {
    public todosModel$ : Observable<TodoModel>;
    //faking an id for demo purposes
    private id: number = 0;

    constructor(
        private _store : Store<AppState>
    ){
        const todos$ = _store.select<Observable<Todo[]>>('todos');
        const visibilityFilter$ = _store.select('visibilityFilter');

...

In the bootstrap, provideStore is given APP_REDUCERS

import {bootstrap} from '@angular/platform-browser-dynamic';
import {TodoApp} from './todo-app';
import {provideStore} from "@ngrx/store";
import * as APP_REDUCERS from "./reducers/reducers";


export function main() {
  return bootstrap(TodoApp, [
      provideStore(APP_REDUCERS)
  ])
  .catch(err => console.error(err));
}

APP_REDUCERS is all the reducers defined. The todos reducer is defined as follows:

    import {ActionReducer, Action} from "@ngrx/store";
import {Todo} from "../common/interfaces";
import {ADD_TODO, REMOVE_TODO, TOGGLE_TODO} from "../common/actions";

export const todos : ActionReducer<Todo[]> = (state : Todo[] = [], action: Action) => {
  switch(action.type) {
      case ADD_TODO:
          return [
              ...state,
              action.payload
          ];

There are a few ways to do this, and you can compose a list of all your reducers, essentially defining a series of object keys that refer to a reducer object.

Store.select returns an observable that you can subscribe to either in your component or template via '|async'.

Derek Kite
  • 1,767
  • 13
  • 15
1

This.store.select('keyname') will return the data from store object of 'keyname' property has. you can further look for inner object in store using multiple reducer with StoreModule.forFeature("master", masterReducer) in main module with createSelector

export const getMasterState = createFeatureSelector<myModels.MasterState>('master');
export const getMatserBranchList = createSelector(
    getMasterState,
    (state: myModels.MasterState): myModels.Branch[] => state.branchList
);
viveksharma
  • 557
  • 4
  • 9