# @larscom/ngrx-signals-storage

> Save signal state (@ngrx/signals) to localstorage/sessionstorage and restore the state on page load (with SSR support).

Latest version **4.1.0** (published 2026-01-18) · MIT license · 0 weekly downloads

## Install

```sh
npm install @larscom/ngrx-signals-storage
pnpm add @larscom/ngrx-signals-storage
yarn add @larscom/ngrx-signals-storage
bun add @larscom/ngrx-signals-storage
```

## Health

**Score 65/100 (B)** — status: stable.

Positive: has types; esm support; no vulnerabilities; has provenance; high maintenance score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 4.1.0 |
| Published | 2026-01-18 |
| First published | 2023-12-24 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 1 |
| Unpacked size | 16.4 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 14 |
| Author | Lars Kniep |
| Maintainers | larscom |
| Keywords | angular, ngrx, redux, store, state, signals, storage, localstorage, sessionstorage, reactive |

## Links

- npm: https://www.npmjs.com/package/@larscom/ngrx-signals-storage
- Repository: https://github.com/larscom/ngrx-signals-storage
- Homepage: https://github.com/larscom/ngrx-signals-storage#readme
- Issues: https://github.com/larscom/ngrx-signals-storage/issues
- npm.io page: https://npm.io/package/@larscom/ngrx-signals-storage

## Dependencies (1)

- [tslib](https://npm.io/package/tslib.md) ^2.3.0

## Alternatives

- [@reckona/mreact-store](https://npm.io/package/@reckona/mreact-store.md) — 976 weekly downloads
- [regular-state](https://npm.io/package/regular-state.md) — 410 weekly downloads
- [@pacote/flux-actions](https://npm.io/package/@pacote/flux-actions.md) — 65 weekly downloads
- [@pilotlab/lux-debug](https://npm.io/package/@pilotlab/lux-debug.md) — 39 weekly downloads
- [vue-persist-state](https://npm.io/package/vue-persist-state.md) — 19 weekly downloads

## Recent versions

- 4.1.0 (latest) — 2026-01-18
- 4.0.2 — 2025-08-14
- 4.0.1 — 2025-07-28
- 4.0.0 — 2025-07-20
- 3.0.0 — 2025-06-05
- 2.1.0 — 2025-01-07
- 2.0.1 — 2024-12-25
- 2.0.0 — 2024-07-26
- 1.2.3 — 2024-07-24
- 1.2.2 — 2024-06-20
- 1.2.1 — 2024-03-23
- 1.2.0 — 2024-02-28
- 1.1.0 — 2023-12-28
- 1.0.0 — 2023-12-25
- 0.0.1 — 2023-12-24

## README

# @larscom/ngrx-signals-storage

[![npm-version](https://img.shields.io/npm/v/@larscom/ngrx-signals-storage.svg?label=npm)](https://www.npmjs.com/package/@larscom/ngrx-signals-storage)
![npm](https://img.shields.io/npm/dw/@larscom/ngrx-signals-storage)
[![license](https://img.shields.io/npm/l/@larscom/ngrx-signals-storage.svg)](https://github.com/larscom/ngrx-signals-storage/blob/main/LICENSE)

> Save signal state (@ngrx/signals) to localStorage/sessionStorage and restore the state on page load with a single line of code (with SSR support).

## Installation

```bash
npm install @larscom/ngrx-signals-storage
```

## Dependencies

`@larscom/ngrx-signals-storage` depends on [@ngrx/signals](https://ngrx.io/guide/signals/install) and [Angular](https://github.com/angular/angular)

## Usage

Import the `withStorage` function and place it after the `withState` function. Optional configuration can be passed as 3th argument.

```ts
import { withStorage } from '@larscom/ngrx-signals-storage'
import { withState, signalStore } from '@ngrx/signals'

export const CounterStore = signalStore(
  withState({
    count: 0
  }),
  // state will be saved to sessionStorage under the key: 'myKey'
  withStorage('myKey', () => sessionStorage)
)
```

## Configuration

```ts
export interface Config<T> {
  /**
   * These keys will not get saved to storage
   */
  excludeKeys: Array<keyof T>

  /**
   * Serializer for the state, by default it uses `JSON.stringify()`
   * @param state the last state known before it gets saved to storage
   */
  serialize: (state: T) => string

  /**
   * Deserializer for the state, by default it uses `JSON.parse()`
   * @param state the last state known from the storage location
   */
  deserialize: (state: string) => T

  /**
   * Save to storage will only occur when this function returns true
   * @param state the last state known before it gets saved to storage
   */
  saveIf: (state: T) => boolean

  /**
   * Removes the state from storage when this function returns true
   * @param state the last state known
   */
  removeIf: (state: T) => boolean

  /**
   * Function that gets executed on a storage error (get/set)
   * @param error the error that occurred
   */
  error: (error: any) => void
}
```

## Save conditionally

Sometimes you only want to save to storage on a specific condition.

```ts
import { withStorage } from '@larscom/ngrx-signals-storage'
import { withState, signalStore } from '@ngrx/signals'

export const CounterStore = signalStore(
  withState({
    count: 0
  }),
  // save only occurs when count is higher than 0
  withStorage('myKey', () => sessionStorage, { saveIf: ({ count }) => count > 0 })
)
```

## Remove conditionally

You might want to remove the state from storage on a specific condition.

```ts
import { withStorage } from '@larscom/ngrx-signals-storage'
import { withState, signalStore } from '@ngrx/signals'

export const CounterStore = signalStore(
  withState({
    count: 0
  }),
  // state gets removed from storage when count is higher than 5
  withStorage('myKey', () => sessionStorage, { removeIf: ({ count }) => count > 5 })
)
```

## Skip properties

Sometimes you want to ignore / exclude properties so they do not get saved into storage. On page reload, the initial value will be loaded instead.

```ts
import { withStorage } from '@larscom/ngrx-signals-storage'
import { withState, signalStore } from '@ngrx/signals'

export const CounterStore = signalStore(
  withState({
    count: 0,
    sum: 0
  }),
  // sum does not get saved into sessionStorage.
  withStorage('myKey', () => sessionStorage, { excludeKeys: ['sum'] })
)
```

## Common Errors

Whenever you get errors this is most likely due to serialization / deserialization of the state.

Objects like `Map` and `Set` are not serializable so you might need to implement your own serialize / deserialize function.

### Serialize / Deserialize

Lets say you have a `Set` in your store, then you need a custom serialize / deserialize function to convert from `Set` to `Array` (serialize) and from `Array` to `Set` (deserialize)

```ts
export const MyStore = signalStore(
  withState({
    mySet: new Set([1, 1, 3, 3])
  }),
  withStorage('myKey', () => sessionStorage, {
    serialize: (state) => JSON.stringify({ ...state, mySet: Array.from(state.mySet) }),
    deserialize: (stateString) => {
      const state = JSON.parse(stateString)
      return {
        ...state,
        mySet: new Set(state.mySet)
      }
    }
  })
)
```

---
_Source: https://npm.io/package/@larscom/ngrx-signals-storage · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
