DEV Community

Jennifer Fadriquela
Jennifer Fadriquela

Posted on

3 3

Base Class for Akita Entities

If you are using Akita for state management, this article might be helpful to you.

// BaseEntityService.ts
import { Observable } from 'rxjs';
import { BaseQuery } from './BaseQuery';
import { EntityStore, EntityState } from '@datorama/akita';
import { tap, delay } from 'rxjs/operators';

export abstract class BaseEntityService<TParams, TView, TResult> {

    constructor(
        protected query: BaseQuery<TView, TParams>,
        protected entityStore: EntityStore<EntityState<TView>, TView>
        ) {
    }

    protected abstract getFromApi(params: TParams): Observable<TResult>;
    protected abstract getFromStore(params: TParams): Observable<TResult>;

    protected selectFromStore(params: TParams): Observable<TView> {
        return this.query.selectData(params).pipe(
            delay(1), // if removed, ui will not update with current data
        )
    }

    get(params: TParams): Observable<TResult> {
        return this.toggleLoading(
            () => {
                if (!this.query.hasData(params))
                    return this.getFromApi(params);
                else
                    return this.getFromStore(params);
            }
        );
    }

    private toggleLoading<TResult>(o: () => Observable<TResult>) {
        this.entityStore.setLoading(true);
        return o().pipe(
            tap((x) => {
                this.entityStore.setLoading(false);
            })
        )
    }
}
Enter fullscreen mode Exit fullscreen mode

BaseEntityService handles abstraction for getting data from api or store. It also implements custom setting of entity loading property via toggleLoading.

// BaseQuery.ts
import { EntityState, QueryEntity } from "@datorama/akita";
import { filter } from 'rxjs/operators';

export abstract class BaseQuery<TView, TParams> extends QueryEntity<EntityState<TView>, TView> {
    selectData(params: TParams) {
        const key = JSON.stringify(params);
        return this.selectEntity(key).pipe(
            filter(x => !!x)
        )
    }

    selectDataNullable(params: TParams) {
        const key = JSON.stringify(params);
        return this.selectEntity(key);
    }

    hasData(params: TParams) {
        const key = JSON.stringify(params);
        return this.hasEntity(key);
    }
}
Enter fullscreen mode Exit fullscreen mode

BaseQuery contains custom selection of existing store data. In our app, we use stringified parameters as keys.

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

nextjs tutorial video

📺 Youtube Tutorial Series

So you built a Next.js app, but you need a clear view of the entire operation flow to be able to identify performance bottlenecks before you launch. But how do you get started? Get the essentials on tracing for Next.js from @nikolovlazar in this video series 👀

Watch the Youtube series

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay