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

How to get type and payload when dispatched? #259

Closed
dchacke opened this issue Oct 22, 2016 · 6 comments
Closed

How to get type and payload when dispatched? #259

dchacke opened this issue Oct 22, 2016 · 6 comments

Comments

@dchacke
Copy link

dchacke commented Oct 22, 2016

When a new dispatch comes through, how can one capture the type and the payload for that dispatch?

For example, I am subscribing to the store:

this.store.subscribe((s: any) => {
  let json = JSON.stringify(s);
  localStorage.setItem('store', json);
});

In almost all cases, I want to save the store to local storage. However, depending on the dispatched action and payload, there are cases in which I don't want to save it to local storage. Additional parameters, such as action and payload would be nice to determine this.

In other words, I would like to be able to run

this.store
  .filter((store, type, payload) => type !== 'undesired type' && payload.id !== 'undesired id')
  .subscribe((store, type, payload) => /* do whatever, such as store in local storage */ );

If there are other ways to do this, please point me in the right direction.

I have found a way to find the type and payload by subscribing to something like in https://github.com/ngrx/store-log-monitor/blob/master/src/log-monitor/log-monitor.ts#L87, but am finding it to be a bit much code for something this simple.

@awerlang
Copy link

Take a look at https://github.com/ngrx/effects, then subscribe to the Actions object with an @Effect.

@wizardnet972
Copy link

I think you should do it using meta-reducer and localStorageSync.

here is how you can do it:

reducers.ts:

const developmentReducer = compose(
  storageStore,
  storeFreeze, storeLogger(), combineReducers)(reducers);

storageStore.ts:

import { ActionReducer, Action } from '@ngrx/store';
import { localStorageSync } from './storage';

function filter(action: Action): boolean {
    console.log('action', action);
    // do here the condition like: 
    // return action.type !== 'undesired type' && action.payload.id !== 'undesired id';
    return true;
}

export function storageStore(reducer: any): ActionReducer<any> {

    const storage = localStorageSync(['sliceFromTheStateToSave'])(reducer);

    return function (state = {}, action) {
        if (filter(action)) {
            reducer = storage;
        }

        return reducer(state, action);
    };
}


@dchacke
Copy link
Author

dchacke commented Jan 17, 2017

The suggested solutions were too complicated. I ended up implementing a custom function that takes the store object, the payload, and a boolean for whether or not to save the store to local storage.

Implementation:

import { Store, Action } from '@ngrx/store';

export const dispatch = (store: Store<any>, action: Action, storeInLocalStorage = true) => {
  store.dispatch(action);

  if (storeInLocalStorage) {
    store.first().subscribe((s: any) => {
      let json = JSON.stringify(s);
      localStorage.setItem('store', json);
    });
  }
};

Usage (e.g. in an Angular 2 component, into which the store has been injected):

dispatch(this.store, { /* payload */ }, false); // true by default, will save to local storage

For anyone stumbling upon this looking for a solution to a similar problem, this solution fixes this particular problem. However, I'm hesitant to close this issue as I think this solution is not universally applicable. Having access to the type and payload object whenever a dispatch occurs would have much further reach.

@littleStudent
Copy link

why did you not consider @awerlang suggestion? I would definitely solve this with effects.

@awerlang
Copy link

@dchacke you're right, you've come up with a solution that doesn't scales.

I'm afraid I was too synthetic at that time, and it wasn't enough for you to take a peek at ngrx/effects, so here's a bit more.

  @Effect({dispatch: false}) storeLocal: this.actions
    .ofType(ACTION1, ACTION2)
    .withLatestFrom(this.store)
    .do(([action, store]) =>
      let json = JSON.stringify(store);
      localStorage.setItem('store', json);
    );

The logic around storeInLocalStorage is encoded in .ofType() above.

@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
None yet
Projects
None yet
Development

No branches or pull requests

5 participants