@gernsdorfer/ngrx-lite
v22.0.0
Published
[](https://www.npmjs.com/package/@gernsdorfer/ngrx-lite) [](https://www.npmjs.com/package/@gernsdorfer/ngrx-lite?act
Maintainers
Readme
NgRxLite
Component-scoped state for Angular that still shows up in the Redux DevTools.
@ngrx/component-store keeps state next to the component that owns it, but that state lives in its own isolated store — invisible to @ngrx/store and to the Redux DevTools.
NgRxLite bridges the two. You keep the ComponentStore API you already know, and every store registers itself in the global state tree, so you get action logs, state import, and time travel across routes for free.
Documentation · Live demo · Sample app source
Why NgRxLite
- Same API as
@ngrx/component-store— plus optional extras, nothing to relearn. - Visible in the DevTools —
setStateandpatchStatebecome real NgRx actions with custom names, and time travel works across routes. - Loading state built in — effects manage
isLoading,itemanderrorfor you, notapResponseboilerplate. - You pick the scope — root, a route, or the component, with multiple instances of the same store when you need them.
Quick start
npm install @gernsdorfer/ngrx-lite @ngrx/store @ngrx/effects @ngrx/component-store @ngrx/operators @ngrx/store-devtoolsProvide the NgRx root store once:
// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideEffects } from '@ngrx/effects';
import { provideStore } from '@ngrx/store';
export const appConfig: ApplicationConfig = {
providers: [provideStore({}), provideEffects([])],
};Then create a store wherever you need one:
// counter.component.ts
import { Component, inject, OnDestroy } from '@angular/core';
import { StoreFactory } from '@gernsdorfer/ngrx-lite';
@Component({
selector: 'my-counter',
template: `
<h2>{{ counterState().counter }}</h2>
<button (click)="increment()">+</button>
`,
})
export class CounterComponent implements OnDestroy {
private store = inject(StoreFactory).createComponentStore<{ counter: number }>({
storeName: 'BASIC_COUNTER',
defaultState: { counter: 0 },
});
// state is a Signal
public counterState = this.store.state;
increment() {
this.store.patchState(({ counter }) => ({ counter: counter + 1 }), 'INCREMENT');
}
ngOnDestroy() {
this.store.ngOnDestroy();
}
}That's it — the store now appears in the Redux DevTools as BASIC_COUNTER.
Features
| Feature | What it does |
| ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- |
| Component Store | setState / patchState with named actions, effects, and action listeners |
| Loading Store | effects that manage isLoading, item and error — with caching and repeat options |
| Reactive Loading | bind a Signal source to the loading lifecycle, with automatic request cancellation |
| Functional Store | create stores as functions — root or lazy, multiple named instances |
| Form Store | two-way sync between a FormGroup and your state, for persistence and debugging |
| Storage Plugins | keep a store in sessionStorage or localStorage, or plug in your own |
| Router Store | record the URL with each state change and replay it by revisiting the route |
| Shared Actions | react to store changes from a global @ngrx/effects effect |
| Testing | storeTestingFactory() mocks the redux store in one line |
Compatibility
| ngrx-lite | Angular | NgRx | | --------- | ------- | ---- | | 22.x | 22.x | 22.x | | 21.x | 21.x | 21.x |
Contributing
Issues and pull requests are welcome. Run yarn start to serve the sample app, nx test store for the library
tests, and nx e2e sample-app-e2e for the end-to-end suite.
License
MIT © Lars Wiedemann
