Tabea
Tabea

Reputation: 93

Difference between directly providing ComponentStore and using provideComponentStore in Angular Standalone Components

I'm working with standalone Angular components and experimenting with the NgRx Component Store. I'm facing confusion regarding the correct way to inject the component store into a component. Here's how I've been providing the store in my component:

@Component({
    selector: 'example-selector',
    standalone: true,
    providers: [ExampleStore],
    templateUrl: './comparison-view.component.html',
    styles: [],
    imports: [
        CommonModule
    ],
})
export class ExampleComponent implements OnInit {
...
}

However, I came across the provideComponentStore method in the NgRx documentation:

import { provideComponentStore } from '@ngrx/component-store';

@Component({
    selector: 'example-selector',
    standalone: true,
    providers: [provideComponentStore(ExampleStore)],
    templateUrl: './comparison-view.component.html',
    styles: [],
    imports: [
        CommonModule
    ],
})
export class ExampleComponent implements OnInit {
...
}

Both methods seemed to work in my application, and I could utilize the store without any issues. What's the exact difference between these two approaches, and which one is recommended for my use case?

Using Version 16.x of @ngrx/store

Upvotes: 0

Views: 985

Answers (2)

rasiaq
rasiaq

Reputation: 73

You should use provideComponentStore() method if you are planning to use lifecycle hooks such as OnStoreInit, OnStateInit or OnDestroy. See: https://ngrx.io/guide/component-store/lifecycle
Also, if you do not register your component store using provideComponentStore() and you use one of the hooks, you will see warning in browser console. It's also mentioned in the docs:

If you implement the lifecycle hooks in the ComponentStore, and register it with providers without using provideComponentStore(), in development mode, a warning is logged to the browser console.

Upvotes: 1

Matthieu Riegler
Matthieu Riegler

Reputation: 54619

When in doubt, always check the source code !

export function provideComponentStore<T extends object>(
  componentStoreClass: Type<ComponentStore<T>>
): Provider[] {
  const CS_WITH_HOOKS = new InjectionToken<ComponentStore<T>>(
    '@ngrx/component-store ComponentStore with Hooks'
  );

  return [
    { provide: CS_WITH_HOOKS, useClass: componentStoreClass },
    {
      provide: componentStoreClass,
      useFactory: () => {
        const componentStore = inject(CS_WITH_HOOKS);

        // Set private property that CS has been provided with lifecycle hooks
        componentStore['ɵhasProvider'] = true;

        if (isOnStoreInitDefined(componentStore)) {
          componentStore.ngrxOnStoreInit();
        }

        if (isOnStateInitDefined(componentStore)) {
          componentStore.state$
            .pipe(take(1))
            .subscribe(() => componentStore.ngrxOnStateInit());
        }

        return componentStore;
      },
    },
  ];

As you can see, this method will run the lifecycle hooks defined on the ComponentStore (as mentioned in the docs).

Upvotes: 1

Related Questions