store icon indicating copy to clipboard operation
store copied to clipboard

🚀[FEATURE]: Action status stream listener decorators

Open futbotism opened this issue 7 years ago • 7 comments

Great library, im really finding ngxs's clean and straightforward approach a joy to write with

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Performance issue
[x] Feature request
[ ] Documentation issue or request
[ ] Support request => https://github.com/ngxs/store/blob/master/CONTRIBUTING.md
[ ] Other... Please describe:

Current behavior

As far as i know this is the only way to subscribe to an action status

this.actions$.pipe(ofActionSuccessful(CartDelete)).subscribe(...)

Expected behavior

It would be neat if we could do this

  @Action(ReadReport)
  readReport(ctx: ReportStateContext) {
    ctx.patchState({ isLoading: true });
    return this.reportsService
      .getReports();
  }

  @ofActionSuccessful(ReadReport) // automatically called as part of action lifecycle
  readReportSuccess(ctx: ReportStateContext, data: Data) {
    ctx.patchState({ data });
  }

  @ofActionFailure(ReadReport) // automatically gets called if ReadReport action throws error
  readReportFailure(ctx: ReportStateContext, error: Error) {
    ctx.patchState({ error });
  }

This would reduce the boilerplate for traditional actions declarations and allows us to hook into the ngxs action stream more easily.

futbotism avatar Nov 06 '18 10:11 futbotism

I like the concept but the tricky thing is that dispatching the action is a multicast. ie. The ReadReport action could be handled by multiple states, and could even be handled multiple times within this state. How would the value of data be determined? It would represent multiple return values.

I could foresee a syntax like this: @Action(ofActionSuccessful(ReadReport)) But the value of the result is still a bit difficult to assertain.

markwhitfeld avatar Nov 06 '18 11:11 markwhitfeld

Ah i didn't see that the ofActionSuccessful pipeable operator doesn't actually deliver a value in its stream...

Yea i would rather use the ngxs built in action statuses than have to dispatch success and failure actions for every request.

On a side note, do you recommend using the patter of dispatching success and failure actions as a result of a request? eg.

ReadReport = '[Report] read report';
ReadReportSuccess  = '[Report] read report success';
ReadReportFailure  = '[Report] read report failure';

futbotism avatar Nov 06 '18 12:11 futbotism

@futbotism https://github.com/ngxs-labs/emitter#lifecycle

what do you think about the simplified use of the actions

splincode avatar Nov 06 '18 13:11 splincode

I did have a look at this pattern, and the simplification looks appealing, but i'm reluctant to move away from redux currently

futbotism avatar Nov 06 '18 13:11 futbotism

@futbotism

IMHO you could centralize everything in one place without the need to listen to ofActionSuccessful | ofActionErrored that might have side effects. NGXS can easily handle asynchronous actions.

Look at the code below:

@Action(ReadReport)
readReport(ctx: ReportStateContext) {
  ctx.patchState({ isLoading: true });

  return this.reportsService.getReports().pipe(
    tap((data) => ctx.patchState({ data }))
    catchError((error) => {
      ctx.patchState({ error });
      return throwError(error);
    }),
    finalize(() => ctx.patchState({ isLoading: false }))
  );
}

Or using async/await:

@Action(ReadReport)
async readReport(ctx: ReportStateContext) {
  ctx.patchState({ isLoading: true });

  try {
    const data = await this.reportsService.getReports().toPromise();
    ctx.patchState({ data });
  } catch (error) {
    ctx.patchState({ error });
    throw error;
  } finally {
    ctx.patchState({ isLoading: false });
  }
}

arturovt avatar May 23 '19 21:05 arturovt

@arturovt I think we update example into documentation

splincode avatar May 23 '19 22:05 splincode

@markwhitfeld https://stackblitz.com/edit/ngxs-of-manage-operation

splincode avatar Oct 08 '19 20:10 splincode

Duplicate https://github.com/ngxs/store/issues/488

splincode avatar Nov 04 '19 21:11 splincode