All Projects → SaulMoro → ngrx-rtk-query

SaulMoro / ngrx-rtk-query

Licence: MIT license
Make RTK Query with Hooks works in Angular Applications

Programming Languages

typescript
32286 projects
javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to ngrx-rtk-query

angular-cli-skeleton
angular-cli skeleton to quickly start a new project with advanced features and best practices. All features are described in README.md.
Stars: ✭ 32 (+23.08%)
Mutual labels:  ngrx
ts-reducer-creator
TypeScript strongly typed boilerplate-free reducer creator for Redux and ngrx
Stars: ✭ 41 (+57.69%)
Mutual labels:  ngrx
angular-cli-ngrx
Sample Blog app using Angular CLI, Ngrx and Ngrx/Effects
Stars: ✭ 30 (+15.38%)
Mutual labels:  ngrx
ngrx-slice
Moved to https://github.com/nartc/nartc-workspace
Stars: ✭ 50 (+92.31%)
Mutual labels:  ngrx
tracks
Angular2 progressive web app for tracking things
Stars: ✭ 23 (-11.54%)
Mutual labels:  ngrx
community-events-angular
Community Events App built with ❤️ using Angular, NgRx, Rxjs to do thrill in #hacktoberfest21
Stars: ✭ 20 (-23.08%)
Mutual labels:  ngrx
angular2-webpack-advance-starter
An advanced Angular2 Webpack Starter project with support for ngrx/store, ngrx/effects, ng2-translate, angulartics2, lodash, NativeScript (*native* mobile), Electron (Mac, Windows and Linux desktop) and more.
Stars: ✭ 49 (+88.46%)
Mutual labels:  ngrx
kanban-project-management
Web Application to manage software development projects.
Stars: ✭ 39 (+50%)
Mutual labels:  ngrx
flux-action-class
Boilerplate free class-based action creator. Following flux-standard-action spec. Built with TypeScript. Works with redux and ngrx.
Stars: ✭ 22 (-15.38%)
Mutual labels:  ngrx
electron-angular-ngrx
An Angular (6x) Electron seed featuring @angular/cli, @ngrx/platform, and Typescript. Complete with HMR workflow
Stars: ✭ 39 (+50%)
Mutual labels:  ngrx
meditation-plus-angular
DEVELOPMENT MOVED TO
Stars: ✭ 15 (-42.31%)
Mutual labels:  ngrx
ngrx-form
Reactive Forms bindings for NGRX and Angular
Stars: ✭ 46 (+76.92%)
Mutual labels:  ngrx
ngrx-best-practice
No description or website provided.
Stars: ✭ 21 (-19.23%)
Mutual labels:  ngrx
todo-app-ngrx
TodoMV* - Angular + Redux (ngrx)
Stars: ✭ 42 (+61.54%)
Mutual labels:  ngrx
ionic4-ngrx-firebase
A basic application for Ionic 4 with firebase & ngrx actions, reducers and effects
Stars: ✭ 17 (-34.62%)
Mutual labels:  ngrx
spring-kotlin-angular4
Another abadoned Spring Boot application with Angular and Kotlinabandoned
Stars: ✭ 22 (-15.38%)
Mutual labels:  ngrx
ng-math
Math Flashcard Progressive Web App built with Angular 2
Stars: ✭ 17 (-34.62%)
Mutual labels:  ngrx
editor.sh
Yet another live programming environment for collaborative code editing and running.
Stars: ✭ 29 (+11.54%)
Mutual labels:  ngrx
Expenses
Keep track of your expenses the smart way 💰
Stars: ✭ 15 (-42.31%)
Mutual labels:  ngrx
angular-workshop
Learning Angular: From component state to NgRx
Stars: ✭ 40 (+53.85%)
Mutual labels:  ngrx


MIT commitizen PRs styled with prettier All Contributors ngneat-lib semantic-release

ngrx-rtk-query is a plugin to make RTK Query (including auto-generated hooks) works in Angular applications with NgRx!! Mix the power of RTK Query + NgRx + RxJS to achieve the same functionality as in the RTK Query guide with hooks.

Table of Contents

Installation

⚠️ ngrx-rtk-query library requires TypeScript 4.1 or higher.

Versions

Angular ngrx-rtk-query @reduxjs/toolkit Support
13.x 3.x.x 1.8.x Bugs / New Features
11.x - 12.x 2.3.0 1.6.2 None

Only the latest version of Angular in the table above is actively supported. This is due to the fact that compilation of Angular libraries is incompatible between major versions.

You can install it through Angular CLI:

ng add ngrx-rtk-query

or with npm:

npm install ngrx-rtk-query

When you install using npm or yarn, you will also need to import StoreRtkQueryModule in your app.module. You can also set setupListeners here.:

import { StoreRtkQueryModule } from 'ngrx-rtk-query';

@NgModule({
  imports: [
    ... // NgRx Modules here!!
    StoreRtkQueryModule.forRoot({ setupListeners: true })
  ],
})
class AppModule {}

Basic Usage

You can follow the official RTK Query guide with hooks, with slight variations.

You can see the application of this repository for more examples.

First, you need to install redux-toolkit:

npm install @reduxjs/toolkit

We'll create a service definition that queries the publicly available

import { fetchBaseQuery } from '@reduxjs/toolkit/query';
import { createApi } from 'ngrx-rtk-query';

export interface CountResponse {
  count: number;
}

export const counterApi = createApi({
  reducerPath: 'counterApi',
  baseQuery: fetchBaseQuery({ baseUrl: '/' }),
  tagTypes: ['Counter'],
  endpoints: (build) => ({
    getCount: build.query<CountResponse, void>({
      query: () => ({
        url: `count`,
      }),
      providesTags: ['Counter'],
    }),
    incrementCount: build.mutation<CountResponse, number>({
      query: (amount) => ({
        url: `increment`,
        method: 'PUT',
        body: { amount },
      }),
      invalidatesTags: ['Counter'],
    }),
    decrementCount: build.mutation<CountResponse, number>({
      query: (amount) => ({
        url: `decrement`,
        method: 'PUT',
        body: { amount },
      }),
      invalidatesTags: ['Counter'],
    }),
  }),
});

export const {
  useGetCountQuery,
  useIncrementCountMutation,
  useDecrementCountMutation,
} = counterApi;

Add the service to your store

export const reducers: ActionReducerMap<RootState> = {
  [counterApi.reducerPath]: counterApi.reducer,
};

@NgModule({
  imports: [
    StoreModule.forRoot(reducers, {
      metaReducers: [counterApi.metareducer],
    }),
    StoreRtkQueryModule.forRoot({ setupListeners: true }),

    !environment.production ? StoreDevtoolsModule.instrument() : [],
  ],
})
export class CoreStoreModule {}

Use the query in a component

import { useDecrementCountMutation, useGetCountQuery, useIncrementCountMutation } from '@app/core/services';

@Component({
  selector: 'app-counter-manager',
  template: `
    <section>
      <button
        *ngIf="increment.state$ | async as incrementState"
        [disabled]="incrementState.isLoading"
        (click)="increment.dispatch(1)"
      > + </button>

      <span *ngIf="countQuery$ | async as countQuery">{{ countQuery.data?.count || 0 }}</span>

      <button
        *ngIf="decrement.state$ | async as decrementState"
        [disabled]="decrementState.isLoading"
        (click)="decrement.dispatch(1)"
      > - </button>
    </section>
  `,
})
export class CounterManagerComponent {
  countQuery$ = useGetCountQuery();
  increment = useIncrementCountMutation();
  decrement = useDecrementCountMutation();
}

Usage

Use on code-splitted/feature/lazy modules

To introduce a lazy/feature/code-splitted query, you must export it through an angular module. Import this module where needed. You can look at posts feature example from this repository.

// ...

export const postsApi = createApi({
  reducerPath: 'postsApi',
  baseQuery: baseQueryWithRetry,
  tagTypes: ['Posts'],
  endpoints: (build) => ({
    // ...
  }),
});

// ...

@NgModule({
  imports: [StoreModule.forFeature(postsApi.reducerPath, postsApi.reducer, { metaReducers: [postsApi.metareducer] })],
})
export class PostsQueryModule {}

Queries

The use of queries is a bit different compared to the original Queries - RTK Query guide. You can look at the examples from this repository.

The parameters and options of the Query can be static or Observables.

The hook useXXXQuery() returns an observable with all the information indicated in the official documentation (including refetch() function). By subscribing to this query (with the async pipe or subscribe()), the query will start its request.

// Use query without params or options
postsQuery$ = useGetPostsQuery();

// Use query with static params or options
postQuery$ = useGetPostsQuery(2, {
  selectFromResult: ({ data: post, isLoading }) => ({ post, isLoading }),
});

// Use query with Observables params or options (can be mixed with static)
postQuery$ = useGetPostsQuery(id$, options$);

Lazy Queries

The use of lazy queries is a bit different compared to the original. As in the case of queries, the parameters and options of the Query can be static or Observables. You can look at lazy feature example from this repository.

Like in the original library, a lazy returns a object (not array) of 3 items, but the structure and naming of the items is different.

  • fetch(arg): This function is the trigger to run the fetch action.
  • state$: Observable that returns an object with the query state.
  • lastArg$: Observable that returns the last argument.
// Use query without options
postsQuery = useLazyGetPostsQuery();
// Use query with static options
postQuery = useLazyGetPostsQuery({
  selectFromResult: ({ data: post, isLoading }) => ({ post, isLoading }),
});
// Use query with Observable options
postQuery = useLazyGetPostsQuery(options$);

Use when data needs to be loaded on demand

<span *ngIf="xxxQuery.state$ | async as xxxQuery">{{ xxxQuery.data }}</span>
<span>{{ xxxQuery.lastArg$ | async }}</span>

//...

export class XxxComponent {
  xxxQuery = useLazyGetXxxQuery();

// ...

  xxx(id: string) {
    this.xxxQuery.fetch(id);
  }

// ...

Another good use case is to work with nested or relational data

<ng-container *ngIf="locationQuery.state$ | async as locationQuery">
//...
</ng-container>

export class CharacterCardComponent implements OnInit {
  @Input() character: Character;

  locationQuery = useLazyGetLocationQuery();

  ngOnInit(): void {
    this.locationQuery.fetch(this.character.currentLocation, { preferCacheValue: true });
  }

// ...

preferCacheValue is false by default. When true, if the request exists in cache, it will not be dispatched again. Perfect for ngOnInit cases. You can look at pagination feature example from this repository.

Mutations

The use of mutations is a bit different compared to the original Mutations - RTK Query guide. You can look at the examples from this repository.

Like in the original library, a mutation is a object (not array) of 2 items, but the structure and naming of the items is different.

  • dispatch(params): This function is the trigger to run the mutation action.
  • state$: Observable that returns an object with the state, including the status flags and other info (see official docs).
// Use mutation hook
addPost = useAddPostMutation();

// Mutation trigger
addPost.dispatch({params});
// Observable with the state of mutation
addPost.state$

FAQ


Contributors

Thanks goes to these wonderful people (emoji key):


Saul Moro

💬 🐛 💻 🖋 🎨 📖 💡 🤔 🚧 🧑‍🏫 📦 🔬 👀

adrian-pena-castro

🐛 💻 🖋 📖 💡 🤔 🚧 🌍

This project follows the all-contributors specification. Contributions of any kind welcome!

Icons made by Freepik from www.flaticon.com
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].