angularngrx-storeangular-standalone-componentsangular2-providersngrx-component-store

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


Solution

  • 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).