Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 137 additions & 0 deletions src/pages/snippets/component-store-with-global-state.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
---
title: Global NgRx State and NgRx Component Store
description: "Pull in global state and use in Component Store"
tags: ["angular", "ngrx", "state"]
pubDate: Feb 25, 2023
contributedBy: "@JayCooperBell"
---

An example of a simple global NgRx Store that is used in a ComponentStore that reacts to global state changes and manipulates
the rest.

Set up a global NgRx Store with Effects.
```typescript
import { createAction, createFeature, createReducer, on } from '@ngrx/store';
import { createEffect } from '@ngrx/effects';
import { interval, map } from 'rxjs';

interface CounterState {
counter: number;
}

const initialCounterState: CounterState = {
counter: 0,
};

export const incrementCounter = createAction(
'[Angular Snippets Example] Increment Counter'
);

export const counterState = createFeature({
name: 'counter',
reducer: createReducer(
initialCounterState,
on(incrementCounter, (state) => ({
...state,
counter: state.counter + 1,
}))
),
});

export const { selectCounter } = counterState;

export const incrementCounterEffect = createEffect(
() => interval(1000).pipe(map(() => incrementCounter())),
{ functional: true }
);
```

Add your global state to the application
```typescript


import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { provideState, provideStore } from '@ngrx/store';
import {
counterState,
incrementCounterEffect,
} from './app/global-state-in-component-store';
import { provideEffects } from '@ngrx/effects';

bootstrapApplication(AppComponent, {
providers: [
provideStore({}),
provideState(counterState),
provideEffects({ incrementCounterEffect }),
],
}).catch((err) => console.error(err));
```

Pull the global state into a component store
```typescript
import { Component, inject, Injectable } from '@angular/core';
import { ComponentStore } from '@ngrx/component-store';
import { Store } from '@ngrx/store';
import { Observable, tap } from 'rxjs';
import { AsyncPipe } from '@angular/common';

interface MyState {
counter: number;
}

@Injectable({ providedIn: 'root' })
export class ComponentStoreWithGlobalState extends ComponentStore<MyState> {
readonly counter$ = this.select((state) => state.counter);

private readonly store = inject(Store);

private readonly setCounter = this.updater((state, counter: number) => ({
...state,
counter,
}));

private readonly multiplyGlobalStateByTwo = this.effect(
(origin$: Observable<number>) =>
origin$.pipe(tap((counter) => this.setCounter(counter * 2)))
);

constructor() {
super({ counter: 0 });

this.multiplyGlobalStateByTwo(this.store.select(selectCounter));
}
}

@Component({
selector: 'component-store-with-global-state',
standalone: true,
providers: [ComponentStoreWithGlobalState],
imports: [AsyncPipe],
template: ` <div>{{ counter$ | async }}</div>`,
})
export class ComponentStoreWithGlobalStateComponent {
readonly store = inject(ComponentStoreWithGlobalState);

readonly counter$ = this.store.counter$;
}
```

Use the component
```typescript
import { Component } from '@angular/core';
import { ComponentStoreWithGlobalStateComponent } from './global-state-in-component-store';

@Component({
standalone: true,
selector: 'angular-snippet-examples-root',
template: `
<component-store-with-global-state></component-store-with-global-state>
`,
styles: [],
imports: [
ComponentStoreWithGlobalStateComponent,
],
})
export class AppComponent {}
```