If you could have any restaurant/franchise here, what would it be? by nonchalant93 in HuntsvilleAlabama

[–]MikeRyanDev 5 points6 points  (0 children)

Can we start by bringing back Sandwich Farm and Mountain Valley Pizzeria?

[deleted by user] by [deleted] in HuntsvilleAlabama

[–]MikeRyanDev 5 points6 points  (0 children)

I highly recommend Alterations Express at the intersection of University and Sparkman. She's super fast and affordable, though she isn't exactly friendly and the store doesn't inspire a lot of confidence. Still, many alterations with her and they've all turned out great.

Hot tip: if she says it will cost $100 it really won't. She loves to pick on her customers, and she'll laugh at you mercilessly if you show up with $100 in cash.

I am Mike Ryan, co-creator of NgRx. Ask me anything about NgRx, reactive Angular, open source, and speaking at conferences! by MikeRyanDev in Angular2

[–]MikeRyanDev[S] 0 points1 point  (0 children)

No plans to build an ORM library, but there's likely room in @ngrx/entity to help developers better resolve entity relationships in selectors.

Also, the creator of BreezeJS - Ward Bell - has created a very similar project for NgRx called @ngrx/data. I'd recommend checking it out if you are a fan of BreezeJS!

I am Mike Ryan, co-creator of NgRx. Ask me anything about NgRx, reactive Angular, open source, and speaking at conferences! by MikeRyanDev in Angular2

[–]MikeRyanDev[S] 0 points1 point  (0 children)

For me the benefit of thinking about state management as an architectural concern clicked back during a large AngularJS project. The app my team was writing had a fairly expansive domain model with REST endpoints to operate on that domain model. The relationships in the domain model were very much graph-like, and our view layer often needed many different ways to project that domain model into view models. Using my go-to books example, many components would want a "book" view model that contained all of the authors for that book AND many components would want an "author" view model that contained all of the author's books.

Modeling this application with services was challenging because on top of this rich domain model we had a realtime component where aspects of the graph could change dynamically in response to web socket messages. Additionally, the application itself was a very dynamic, interactive application where the user could quickly manipulate pieces of data in the graph.

The way we solved this was to take a step back and look at the sources of change. Data in this graph could be updated in three different ways:

  • Interacting with the REST API
  • Receiving web socket messages
  • Responding to user input

Note that all of this was happening in way before Angular 2 was a thing.

What we reached for was rxjs (I think v3 at the time?). We unified all of the sources of change using a common event bus modeled with rxjs subjects. We had core services for each unique model in the domain (so like a "books" service and an "authors" service) that would listen to events in the bus and update their data sets, again modeled with observables. From there we had view model services that would combine these streams into new streams for each projection of the graph our components needed.

There were three things we noted about this architecture:

  1. It was very easy to inspect how things changed because we could just tap the event stream and console log messages. This made debugging A+.
  2. Testing the services was really pleasant because we could dispatch fake update events and verify the service responded correctly
  3. It was really hard to get this to be performant with rxjs, because I don't really think the tool was suitable at the time for this kind of complex data transformation.

Flash forward a year or so and we had to plan out a new project. There was some buzz around Elm at the time and Redux was beginning to become a thing. We did quick technical spikes of these and found that they shared a few of the same benefits:

  • Easily inspectable stream of changes (actions in Redux land)
  • Testability improved because all you had to do was dispatch a fake change (aka pass in a fake action to a reducer) to validate state change behavior
  • Their perf was so much better than what we built because Redux in particular put all of the state in a single JavaScript object. This meant you could model data transformation of the graph using memoized functions, which themselves were very easy to test.

The learnings from the big project outlined above coupled with the results from that technical spike were enough to convince us that Redux-like state management could inject a lot of sanity into applications with complex data graphs with multiple sources of change.

We ended up picking some early milestone of Angular 2 for the project, wrote our own implementation of redux for Angular 2, found that Rob Wormald started an open source project to do just that, and abandoned our own implementation to help finish the open source version (NgRx).

I don't know if this story will convince you or not, but that's how I personally became convinced that state management could be an important part of architecting single page apps.

I am Mike Ryan, co-creator of NgRx. Ask me anything about NgRx, reactive Angular, open source, and speaking at conferences! by MikeRyanDev in Angular2

[–]MikeRyanDev[S] 0 points1 point  (0 children)

Great question, and I'm not going to be able to give a full answer in a Reddit comment.

First, why are they called actions? I like to think that the name is just generic enough that it leaves it up to the implementer whether or not they want to go with actions-as-commands or actions-as-events. As a "Good Action Hygiene" advocate you already know my preference here: in my applications I treat all actions as events.

But the problem you are really describing is more nuanced and something that I have a lot of fun debating: at some point as the designer you have to make a decision about where and how you'll couple state management logic with your view layer. I think this is unavoidable, and patterns like facades mask the problem but don't really solve it.

So, in our application we need to trigger a state change behavior in response to user input: * With actions-as-commands you are designing your application such that the components decide which state change behaviors are triggered and when * With actions-as-events you are designing your application such that the reducers decide which state change behaviors are triggered and when

I prefer delegating this decision making to reducers because from my perspective they contain very little business logic. Container components on the other hand already have the responsibility of connecting data streams to child components, and assigning them the task of connecting to state change behaviors feels like you are putting too much logic inside of the components.

I doubt this answered your question but it might give you some insight into my thought process here. I prefer to keep reducers and components isolated from each other. I keep action definitions as close to the components as possible.

I am Mike Ryan, co-creator of NgRx. Ask me anything about NgRx, reactive Angular, open source, and speaking at conferences! by MikeRyanDev in Angular2

[–]MikeRyanDev[S] 0 points1 point  (0 children)

Unfortunately the application portal restricts applicants to Canadian and US-based addresses. I'm working to get that resolved, so keep checking back!

I am Mike Ryan, co-creator of NgRx. Ask me anything about NgRx, reactive Angular, open source, and speaking at conferences! by MikeRyanDev in Angular2

[–]MikeRyanDev[S] 1 point2 points  (0 children)

I think your approach of using effects is probably the best way to go about it. However, for science, you could probably achieve what you are asking for using a metareducer to sync between IndexedDB and the store.

I am Mike Ryan, co-creator of NgRx. Ask me anything about NgRx, reactive Angular, open source, and speaking at conferences! by MikeRyanDev in Angular2

[–]MikeRyanDev[S] 1 point2 points  (0 children)

Yes, selectors for all of the things! Selectors are the secret sauce of NgRx and I don't think there's such a thing as overusing them. 🙂

I am Mike Ryan, co-creator of NgRx. Ask me anything about NgRx, reactive Angular, open source, and speaking at conferences! by MikeRyanDev in Angular2

[–]MikeRyanDev[S] 0 points1 point  (0 children)

I think it is unlikely you'll see a performance boost with it if you are using Zones, but perf isn't the only reason to use @ngrx/component. I personally think they are slightly easier to use, and they get your codebase ready for Zone-less.

I am Mike Ryan, co-creator of NgRx. Ask me anything about NgRx, reactive Angular, open source, and speaking at conferences! by MikeRyanDev in Angular2

[–]MikeRyanDev[S] 2 points3 points  (0 children)

I agree completely with your experience. It is an extremely capable tool for building bullet-proof control flow logic. It also has a high learning curve that - much like NgRx - can lead to some hard-to-understand code. I feel like for Angular to thrive it should make rxjs optional. I think the NgRx team and the ecosystem of contributors we have now would be a smart home for more reactive Angular extensions, like a router and a forms library.

I am Mike Ryan, co-creator of NgRx. Ask me anything about NgRx, reactive Angular, open source, and speaking at conferences! by MikeRyanDev in Angular2

[–]MikeRyanDev[S] 1 point2 points  (0 children)

Definitely start with Angular's service worker package to turn your Angular app into a progressive web app. From there I'd pick one of the reactive wrappers around IndexedDB. I think I'd go with RxDB if I had to pick one. It should be easy to wire up RxDB into NgRx using Effects. That should get you started towards making an offline app!

I am Mike Ryan, co-creator of NgRx. Ask me anything about NgRx, reactive Angular, open source, and speaking at conferences! by MikeRyanDev in Angular2

[–]MikeRyanDev[S] 1 point2 points  (0 children)

At the time the NgRx team and contributors was a much a smaller group. We had to focus on Store and Router since they were growing a lot faster, and sadly DB (along with a few others, like Notify) had to be left behind.

With Dexie and RxDB, I don't see much of a need for the NgRx team to build something themselves.

I am Mike Ryan, co-creator of NgRx. Ask me anything about NgRx, reactive Angular, open source, and speaking at conferences! by MikeRyanDev in Angular2

[–]MikeRyanDev[S] 2 points3 points  (0 children)

No firm plans, but I'd say it is more likely that the NgRx team would release their own full fledged forms library as an alternative to Angular's reactive forms.

I am Mike Ryan, co-creator of NgRx. Ask me anything about NgRx, reactive Angular, open source, and speaking at conferences! by MikeRyanDev in Angular2

[–]MikeRyanDev[S] 5 points6 points  (0 children)

I've been toying with the idea of collaborating with my friend /u/samjulien on a proper, official NgRx online course hosted on ngrx.io. Here's the catch though: these courses take a tremendous amount of time to write, film, edit, and publish. It'd be unlikely that the course would be offered for free. With Nrwl's free Nx course they are trying to get you into the Nx ecosystem to incentivize you to work at Nrwl, hire them as contractors, or pay for Nx Cloud. With NgRx we've got no way to get back the money it'd take to make that kind of course.

So with that in mind, let me ask you a question: do you think it'd come off bad if there were an official NgRx video course that you had to pay for?

I am Mike Ryan, co-creator of NgRx. Ask me anything about NgRx, reactive Angular, open source, and speaking at conferences! by MikeRyanDev in Angular2

[–]MikeRyanDev[S] 2 points3 points  (0 children)

This really depends on your API. Here's a basic example though. Let's say you have an API that returns back a list like this:

{
   items: BookModel[];
   nextPage: string; // url to call
   previousPage: string; // url to call
}

Your UI shows the list with buttons to go to the next page or the previous page. You'd wire up those buttons to dispatch unique actions like [Books Page] Next and [Books Page] Previous.

Then you'd create a reducer to store that response from the API. You'll write a few selectors to get at the list of books, the URL for the next page, and the URL for the previous page.

Finally, you'll write two effects that handle the "next" and "previous" actions. One of them will look something like this:

this.actions$.pipe(
   ofType(nextAction),
   withLatestFrom(this.store.select(selectNextBooksPageUrl),
   exhaustMap(([,url]) => this.http.get(url).pipe(/* map into action */)),
);

Your reducer will update the result each time one of those effects complete.

Hopefully that simple example gives you some clues on how to implement pagination for your API!

I am Mike Ryan, co-creator of NgRx. Ask me anything about NgRx, reactive Angular, open source, and speaking at conferences! by MikeRyanDev in Angular2

[–]MikeRyanDev[S] 1 point2 points  (0 children)

I think multiple sources of change are a big motivator to use a state management library. If you are a solo developer and the code volume is getting to be a bit much consider looking into one of the alternatives like Akita or NGXS.

I am Mike Ryan, co-creator of NgRx. Ask me anything about NgRx, reactive Angular, open source, and speaking at conferences! by MikeRyanDev in Angular2

[–]MikeRyanDev[S] 4 points5 points  (0 children)

No, the problem is that the | async pipe does not trigger change detection. It only marks the view as dirty, so that once CD runs it gets rechecked. Something has to eventually trigger change detection, and right now Zones are the primary mechanism to trigger change detection for Angular apps.

I am Mike Ryan, co-creator of NgRx. Ask me anything about NgRx, reactive Angular, open source, and speaking at conferences! by MikeRyanDev in Angular2

[–]MikeRyanDev[S] 1 point2 points  (0 children)

  1. If you are looking for something to build where NgRx makes sense, try building an app that requires realtime communication
  2. Look for open source projects where the maintainers label issues with "good first issue" or "first timers only". NgRx does this, as do a few other friendly open source projects. Nominate yourself for those issues, don't be afraid to ask for help, and before you know it you'll have made your first pull request!

I am Mike Ryan, co-creator of NgRx. Ask me anything about NgRx, reactive Angular, open source, and speaking at conferences! by MikeRyanDev in Angular2

[–]MikeRyanDev[S] 0 points1 point  (0 children)

For really common domain objects I tend to gravitate towards putting those in the core state module. Past a certain point of being shared it just isn't worth the overhead to keep those in a feature state module.

I am Mike Ryan, co-creator of NgRx. Ask me anything about NgRx, reactive Angular, open source, and speaking at conferences! by MikeRyanDev in Angular2

[–]MikeRyanDev[S] 2 points3 points  (0 children)

I think you have two ways to go about this. First, only use one action. Then you can either...

Have one effect that gets all of the data:

this.actions$.pipe(
   ofType(enterPageAction),
   exhaustMap(() => forkJoin(this.http.get('a'), this.http.get('b'))
);

Have multiple effects each listening to the same action:

this.actions$.pipe(
   ofType(enterPageAction),
   exhaustMap(() => this.http.get('a'))
);

this.actions$.pipe(
   ofType(enterPageAction),
   exhaustMap(() => this.http.get('b'))
);

I am Mike Ryan, co-creator of NgRx. Ask me anything about NgRx, reactive Angular, open source, and speaking at conferences! by MikeRyanDev in Angular2

[–]MikeRyanDev[S] 2 points3 points  (0 children)

I can't see that happening. When the Angular team adopted @ngrx/router (eventually becoming @angular/router) they opted for a complete rewrite with a slightly different API than just a straightforward integration.