NgRx Tutorial: Faster App Development with NgRx 8

NgRx 8 features improved developer ergonomics, less boilerplate, runtime checks, and easier error handling.

NgRx (Reactive Extensions for Angular) is becoming more and more popular in the Angular community. It is a great way to manage state using the redux pattern and keep your application scalable.

NgRx 8 introduces a host of improvements, including createAction, createReducer, and createEffect. These helper functions drastically reduce (no pun intended) boilerplate, which boosts developer productivity.

How to Update to NgRx 8

In order to update to NgRx 8, you’ll need to be sure your project is updated to Angular 8. You can update your Angular CLI globally by running this command:

npm install -g @angular/cli

In a project that needs to be updated to Angular 8, you can run the following:

ng update @angular/cli @angular/core

You can then run the following to update to NgRx 8:

ng update @ngrx/store

When working on this article, I ran into a bit of a problem with the TypeScript version. It seems like there was a conflict between the required versions, so I had to manually lock in version 3.4.3.

If you’re using ngrx-data, you can easily migrate to @ngrx/data with this command:

ng add @ngrx/data --migrate

For more specific details on migration to NgRx 8, check out the official migration guide. Finally, don’t forget that Angular has an official update tool to help with moving to new versions of Angular.

With that out of the way, let’s get to the fun stuff!

createExcitement: The New NgRx 8 Helper Functions

One of the most common complaints about NgRx (and the Redux pattern in general) is that there is too much boilerplate. Once you dig into the library and the pattern, though, you start to understand that the initial setup is a completely worthwhile investment when you’re managing state in large, complex applications (which is what NgRx is designed for!).

That being said, the NgRx team has listened to the developer community and made some huge improvements in “developer ergonomics” (a fancy way to say making it easier to write code) with version 8. Most of these improvements are due to a refactor of how actions, reducers, and effects are set up. There are now helper methods that are easy to understand and take less code to write. Let’s take each of them in turn.

createAction

Great care and attention are required in deciding what actions your app needs. Unfortunately, actions take a lot of code to set up.

// src/auth/actions/auth.actions.ts (excerpt)
export enum AuthActionTypes {
  Login = '[Login Page] Login',
  LoginComplete = '[Login Page] Login Complete',
  LoginFailure = '[Auth API] Login Failure'
}

export class Login implements Action {
  readonly type = AuthActionTypes.Login;
}

export class LoginComplete implements Action {
  readonly type = AuthActionTypes.LoginComplete;
}

export class LoginFailure implements Action {
  readonly type = AuthActionTypes.LoginFailure;

  constructor(public payload: any) {}
}

export type AuthActions =
  | Login
  | LoginComplete
  | LoginFailure;

This excerpt only contains three of the eight actions in that application and it’s a very small app! You can see why a change was needed.

Enter the new createAction method. With createAction, you pass in the action name along with an optional props function with a specified argument type as a destructured object.

Yikes, that’s a lot of jargon. Let me explain that with an example.

Let’s say I have an action called booksLoaded that needs to receive an array of books (books) of type Book[] when created. My props function for createAction would be props(). (With destructuring, { books } is the equivalent of { books: books }.)

export const booksLoaded = createAction(
  '[Books API] Books Loaded', 
  props()
  );

That way, when I create a new action of this type, I can directly pass the array of books into the constructor: new booksLoaded({ booksFromServer }).

So, the above authentication actions would be refactored like so:

export const login = createAction('[Login Page] Login');

export const loginComplete = createAction('[Login Page] Login Complete');

export const loginFailure = createAction(
  '[Auth API] Login Failure', 
  props()
);

Mind-blowing, right?

There are two things to notice here. First, notice that the action constant names have gone from Pascal case (LoginFailure) to camel case (loginFailure). This is due to actions changing from classes to functions and is a standard JavaScript style convention. Don’t let that trip you up, but be mindful of that in refactoring.

Second, notice that I renamed payload to error because it is more descriptive. (I could have also given it a new type like Error, but it doesn’t matter much in this example). While this is a great new feature with the redesigned action creator function, be careful of doing this. Do a search through your code to avoid breaking other parts of the app relying on a payload property. If you rename payload in the action creator, be sure to change it everywhere.

There’s one last great feature of the new action creators. You can now specify a default value of a prop argument. For example, in the above loginFailure action, I could provide a default error message:

export const loginFailure = createAction(
  '[Auth API] Login Failure',
  (errorMessage = 'Error logging in') => ({ payload: { errorMessage }})
);

This would be a great backup in case the server fails to provide an error message for some reason.

To add one of these new action creators to your application, you can use the updated action schematic:

ng generate @ngrx/schematics:action myNewAction --creators

This command will generate a new file called my-new-action.actions.ts containing a constant named loadMyNewAction using the createAction function.

createReducer

The new way to create actions is incredible, but it doesn’t stop there. Reducers are also now easier to write thanks to the createReducer method.

Here’s a typical example of a reducer you might find in a burger restaurant app:

export function reducer(
  state = initialState,
  action: BurgerApiActionsUnion
): State {
  switch (action.type) {
    case BurgerApiActionTypes.LoadBurgerCollection: {
      return { 
        ...state
        loading: true
      };
    }

    case BurgerApiActionTypes.LoadBurgersSuccess: {
      return { 
        loaded: true,
        loading: false,
        ids: action.payload.map(burger => burger.id)
      };
    }

    default: {
      return state;
    }
  }
}

This is a simple example, but as it scales up, you’ll have a ton of case statements that will make understanding this code difficult. It gets messy fast (just like eating burgers, really).

With NgRx 8, you can use createReducer instead:

const burgerReducer = createReducer(
  initialState,
  on(BurgerApiActionTypes.loadBurgerCollection, state => ({
    ...state,
    loading: true
  })),
  on(BurgerApiActionTypes.loadBurgersSuccess, (state, { burgers }) => ({
    loaded: true,
    loading: false,
    ids: burgers.map(burger => burger.id)
  }))
);

Much cleaner, isn’t it? Each case uses the on function that receives the action and a function to modify state.

The on function can also take multiple actions, making it easy to grow the reducer function. For example, it’s common for the success of a record addition and the failure of a record deletion to result in the same state. An example of this is when an app state includes both a collection of data (which should match what’s on the server) and an array of IDs for faster lookup (which is maintained in memory). In order to make sure the array of IDs always matches what’s on the server, it’s necessary to account for failures of adding or deleting records.

Here’s an example of that with the burger application:

const burgerReducer = createReducer(
  // ...other cases,
  on(
    CollectionApiActions.addBurgerSuccess,
    CollectionApiActions.removeBurgerFailure,
    (state, { burger }) => {
      if (state.ids.indexOf(burger.id) > -1) {
        return state;
      }
      return {
        ...state,
        ids: [...state.ids, burger.id],
      };
    }
  ),
  on(
    CollectionApiActions.removeBurgerSuccess,
    CollectionApiActions.addBurgerFailure,
    (state, { burger }) => ({
      ...state,
      ids: state.ids.filter(id => id !== burger.id),
    })
  )
);

Using the same reducer cases for multiple actions makes it easier to understand what’s happening in this application in addition to ensuring the ids array doesn’t get out of sync with the server.

One other important note on using createReducer. As of this writing, the Angular ahead-of-time (AOT) compiler (the compiler used for producing production builds) does not support function expressions. It’s therefore necessary to wrap the createReducer function in an exported function like so:

export function reducer(state: State | undefined, action: Action) {
  return burgerReducer(state, action);
}

Finally, as with createAction, there’s a schematic for the new reducer style:

ng generate @ngrx/schematics:reducer myNewReducer --creators

This schematic will generate a new file called my-new-reducer.reducer.ts. It will include both the createReducer constant and the exported reducer function for AOT.

createEffect

Finally, createEffect is here to improve writing effects. Previously, effects used an @Effect() decorator. While this was fine, it was sort of the odd bird compared to all of the other more functional approaches NgRx takes.

Going back to the burger application, here’s an example of the old style of effect:

@Effect()
loadBurgerCollection$ = this.actions$.pipe(
  ofType(BurgerApiActionTypes.LoadBurgerCollection),
  switchMap(() =>
    this.burgerService.getAllBurgers().pipe(
      map((burgers: Burger[]) =>
        BurgerApiActions.LoadBurgersSuccess({ burgers })
      ),
      catchError(error =>
        of(BurgerApiActions.LoadBurgersFailure({ error }))
      )
    )
  )
);

The new createEffect helper simplifies this a bit and standardizes it to look more like creating actions, reducers, and selectors:

loadBurgerCollection$ = createEffect(() =>
  this.actions$.pipe(
    ofType(BurgerApiActionTypes.loadBurgerCollection),
    switchMap(() =>
      this.burgerService.getCollection().pipe(
        map((burgers: Burger[]) =>
          BurgerApiActions.loadBooksSuccess({ burgers })
        ),
        catchError(error =>
          of(BurgerApiActions.loadBooksFailure({ error }))
        )
      )
    )
  )
);

Remember, the actions have changed from Pascal case to camel case since they’ve changed from classes to functions.

There’s also a small modification in effects that don’t dispatch new actions. Here’s an effect that fires after a burger is successfully ordered, which redirects back to the home page and doesn’t dispatch a new action:

@Effect({ dispatch: false })
orderBurgerSuccess$ = this.actions$.pipe(
  ofType(BurgerApiActions.OrderBurgerSuccess),
  tap(() => {
    this.router.navigate(['/']);
  })
);

Using the new createEffect function, you can refactor this code to the following:

orderBurgerSuccess$ = createEffect(() => 
  this.actions$.pipe(
    ofType(BurgerApiActions.LoginSuccess),
    tap(() => this.router.navigate(['/']))
  ),
  { dispatch: false }
);

That second argument of the createEffect function is for passing in metadata to control how the effect operates.

One final word on effects in NgRx 8. Previously, the team found that developers were either forgetting to handle errors in their effects or handling them incorrectly. To help with this, effects now automatically resubscribe on errors (instead of completing) so they continue to listen to dispatched actions. This is extremely helpful but it can also be disabled if you start noticing weird behaviors. Simply pass { resubscribeOnError: false } as the second argument of the createEffect function.

As with the other two examples, there’s a schematic to add the new style of effect to your application:

ng generate @ngrx/schematics:effect myNewEffect --creators

This command will generate a new file called my-new-effect.effects.ts that imports createEffect and creates a class marked with the Injectable decorator.

Conclusion

I don’t know about you, but I couldn’t be happier with NgRx 8. This is a team of volunteers who are making great software and even writing phenomenal docs. With all of the improvements in this version, the future is looking bright. Give it a test drive and let me know how it goes!

#angular #web-development

What is GEEK

Buddha Community

NgRx Tutorial: Faster App Development with NgRx 8
Fredy  Larson

Fredy Larson

1595059664

How long does it take to develop/build an app?

With more of us using smartphones, the popularity of mobile applications has exploded. In the digital era, the number of people looking for products and services online is growing rapidly. Smartphone owners look for mobile applications that give them quick access to companies’ products and services. As a result, mobile apps provide customers with a lot of benefits in just one device.

Likewise, companies use mobile apps to increase customer loyalty and improve their services. Mobile Developers are in high demand as companies use apps not only to create brand awareness but also to gather information. For that reason, mobile apps are used as tools to collect valuable data from customers to help companies improve their offer.

There are many types of mobile applications, each with its own advantages. For example, native apps perform better, while web apps don’t need to be customized for the platform or operating system (OS). Likewise, hybrid apps provide users with comfortable user experience. However, you may be wondering how long it takes to develop an app.

To give you an idea of how long the app development process takes, here’s a short guide.

App Idea & Research

app-idea-research

_Average time spent: two to five weeks _

This is the initial stage and a crucial step in setting the project in the right direction. In this stage, you brainstorm ideas and select the best one. Apart from that, you’ll need to do some research to see if your idea is viable. Remember that coming up with an idea is easy; the hard part is to make it a reality.

All your ideas may seem viable, but you still have to run some tests to keep it as real as possible. For that reason, when Web Developers are building a web app, they analyze the available ideas to see which one is the best match for the targeted audience.

Targeting the right audience is crucial when you are developing an app. It saves time when shaping the app in the right direction as you have a clear set of objectives. Likewise, analyzing how the app affects the market is essential. During the research process, App Developers must gather information about potential competitors and threats. This helps the app owners develop strategies to tackle difficulties that come up after the launch.

The research process can take several weeks, but it determines how successful your app can be. For that reason, you must take your time to know all the weaknesses and strengths of the competitors, possible app strategies, and targeted audience.

The outcomes of this stage are app prototypes and the minimum feasible product.

#android app #frontend #ios app #minimum viable product (mvp) #mobile app development #web development #android app development #app development #app development for ios and android #app development process #ios and android app development #ios app development #stages in app development

Digital Wallet App Development | Mobile Payment App Development | e-Wallet App Development

Are you looking for the most trusted and custom mobile wallet development company in USA? We at AppClues Infotech offering reliable & productive mobile wallet app development services with advanced technologies and functionalities. Hire dedicated mobile wallet designer & developers from us at the best price for your business requirements.

Our Mobile Wallet App Development Services
• Custom Mobile Wallet App Solution
• Cryptocurrency Wallet App Development
• Digital Wallet App Development
• Mobile Payment App Development
• Mobile Wallet UI/UX Designing

For more info:
Website: https://www.appcluesinfotech.com/
Email: info@appcluesinfotech.com
Call: +1-978-309-9910

#digital wallet app development #mobile payment app development #e-wallet app development #digital e-wallet app development company #digital wallet app development services #ewallet app development

Top Iphone App Development Company USA | Expert Iphone App Developers

If the majority of the target audience uses iPhone then the best idea to launch your business mobile app first is to start with iPhone Mobile App Development. The recent success of app like Clubhouse by first launching the app only for iPhone users has led many to believe that this the way to go forward.

Want to launch an iPhone app for your business needs?

With a portfolio of 250+ iPhone apps developed WebClues Infotech is the right agency that can help you in launching a successful iPhone app for your business. With a flexible pricing structure that suits most businesses as per their need, WebClues Infotech is surely the one-stop solution of every App Development Needs

Want to know more about how WebClues Infotech can help you launch an iPhone app?

For more information click here https://www.webcluesinfotech.com/iphone-app-development/

Contact: https://www.webcluesinfotech.com/contact-us/

View Portfolio: https://www.webcluesinfotech.com/portfolio/

#iphone app development #ios app development #ios app development company #custom iphone app development company #ios app developer #hire ios app developer

First DigiAdd

1622009130

Mobile App Development Services | Android App Development

First DigiAdd is the Best Mobile App Development Service provider. The application has almost taken control of the workspace to use the Internet. Mobile is a must for all people at this time. In this 21st century. Our team develops a unique and fully located portable application that can be easily operated by anyone.

#mobile app development services #best app development company #mobile app development company, #android app development services #ios app development services #web & app development services

Julia Johnson

1618894792

Top App Developers Canada | Mobile App Development Company Canada

iQlance is a top mobile app development company Canada that offers both mobile and web app development services. The company uses different technologies and begin the whole process by understanding the requirement of their clients. From designing and development to launch and post-launch, our top app developers in Canada are second to none. All our expert and professional app developers Canada have many years of expertise to turn your imagination into powerful apps.

iQlance is one of the efficient app development companies in Canada that specializes in building user-friendly apps for every platform. Our app developers use superior technologies in the development procedure to deliver outstanding user experience. Our team possesses the experience and skills to make Android, iOS, Windows, Blackberry, and TV apps.

Get in touch with us to turn your app idea into reality.

https://www.iqlance.com/mobile-app-development/

#app developers canada #top mobile app development company canada #app development companies in canada #top app developers in canada #app development company canada #app development canada