Akita: Angular. How can I detect, what kind of action has updated store data?

Created on 25 Oct 2018  路  8Comments  路  Source: datorama/akita

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Performance issue
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request
[x] Other... Please describe:
Angular - question about store action?

Current behavior


Angular. How can I detect, what kind of action has updated store data?
Example:
1) In component I can call Akita service for GET ITEM and SAVE ITEM.
2) Both are updating store ITEM state.
3) In component I have a Subscription to query, but I have no idea, if store was updated because of GET or SAVE.
4) I need to know it, to make different things in component, according to each action.

I have added 'action' variable to store, where I save this value. But the problem is that, when new component is created and subscribe is created and dispatched immediately, my 'action' vabiable is readed too, which is wrong.

Any ideas, what can I do with it?

Expected behavior

Minimal reproduction of the problem with instructions

What is the motivation / use case for changing the behavior?

Environment


Angular version: 6.Y.Z


Browser:
- [ ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX

For Tooling issues:
- Node version: XX  
- Platform:  

Others:

help wanted

Most helpful comment

You can say so.

All 8 comments

Why do u need to know the action? Can you give me an example, please?

For example, I want to inform user (show message):

  • 'Data has been refreshed' or 'Data has been resetted' for GET ITEM
  • 'Data has been saved' for SAVE ITEM

You can return the http subscription and you will know.

"You can return the http subscription and you will know." -> I don't understand, what should I do.

This is my Akita store:

algorithm.store.ts


export enum AlgorithmStateAction {
  GET = 'GET',
  SAVE = 'SAVE'
}

export interface AlgorithmState {
  action: AlgorithmStateAction;
  algorithm: Algorithm;
}

export function AlgorithmStateCreateInitialState(): AlgorithmState {
  return {
    action: null,
    algorithm: null
  };
}

@Injectable({ providedIn: 'root' })
@StoreConfig({ name: 'algorithm' })
export class AlgorithmStore extends Store {

  constructor() {
    super(AlgorithmStateCreateInitialState());
  }

}
**algorithm.query.ts**

@Injectable({ providedIn: 'root' })
export class AlgorithmQuery extends Query {

  loading$ = this.selectLoading();
  error$ = this.selectError();

  algorithm$ = this.select(state => {
    return state.algorithm;
  });

  get action(): AlgorithmStateAction {
    const snapshot = this.getSnapshot();
    return snapshot.action;
  }

  constructor(protected store: AlgorithmStore) {
    super(store);
  }

}
**algorithm.service.ts**

@Injectable({ providedIn: 'root' })
export class AlgorithmService {

  constructor(
    private algorithmStore: AlgorithmStore,
    private algorithmDataService: AlgorithmDataService
  ) { }

  getAlgorithm() {
    this.algorithmStore.setLoading(true);

this.algorithmDataService.getAlgorithm().subscribe((dataServiceResult: Algorithm) => {
  const algorithm = plainToClass(Algorithm, dataServiceResult);

    this.algorithmStore.update(state => ({
      algorithm: algorithm,
      action: AlgorithmStateAction.GET
    }));
    this.algorithmStore.setLoading(false);
  },
    (err: HttpErrorResponse) => {
      (...)
    });

}

getAlgorithm() {
(...)
this.algorithmStore.update(state => ({
algorithm: algorithm,
action: AlgorithmStateAction.SAVE
}));
(...)
}

clearStore() {
this.algorithmStore.update(state => (AlgorithmStateCreateInitialState()));
this.algorithmStore.setPristine();
}
}

some Angular component


this.algorithmQuery.algorithm$.subscribe(algorithm => {
switch (this.algorithmQuery.action) {
case AlgorithmStateAction.GET:
(...)
break;
case AlgorithmStateAction.SAVE:
(...)
break;
}
});

Like I have written above. The problem is that, when new component is created and subscribe is created and dispatched immediately, my 'action' vabiable is readed too, which is wrong, because action stored in store is some old action, that is not important, even wrong on component initialize, but I can't remove it, because it's necessary for future component store actions.

You can return the subscription:

  getAlgorithm() {
    this.algorithmStore.setLoading(true);

    return this.algorithmDataService.getAlgorithm().pipe(
      tap((dataServiceResult: Algorithm) => {
      const algorithm = plainToClass(Algorithm, dataServiceResult);

        this.algorithmStore.update(state => ({
          algorithm: algorithm,
          action: AlgorithmStateAction.GET
        }));
        this.algorithmStore.setLoading(false);
      },
        (err: HttpErrorResponse) => {
          (...)
        });
  }

And in your component:

getAlgorithm().subscribe(() => {
   // here you know that you finished the get action 
})

saveAlgorithm().subscribe(() => {
   // here you know that you finished the save action 
})

Looks good.
This is like creating an Effect isn't it?

You can say so.

@NetanelBasal
Looks good. Thank you for this idea.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

adraax picture adraax  路  4Comments

hoisel picture hoisel  路  5Comments

eitanfr picture eitanfr  路  4Comments

twittwer picture twittwer  路  7Comments

Tobjoern picture Tobjoern  路  3Comments