|
1 | 1 | --- |
2 | 2 | title: NgRx Store |
3 | | -description: Live NgRx signal stores and @ngrx/store state, with change logs, diffs, restore and dispatch. |
| 3 | +description: Live NgRx signal stores and @ngrx/store state, with entities, dispatched events, change logs, diffs, restore and dispatch. |
4 | 4 | --- |
5 | 5 |
|
6 | 6 | <ngmd-hero title="NgRx Store" logo="https://cdn.simpleicons.org/ngrx/BA2BD2" gradient> |
7 | | - Your NgRx state as it changes. Signal stores and the classic Store, with a log of every change, a diff per entry, restore and dispatch. |
| 7 | + Your NgRx state as it changes. Signal stores and the classic Store, with entity collections, dispatched events, a log of every change, a diff per entry, restore and dispatch. |
8 | 8 | </ngmd-hero> |
9 | 9 |
|
10 | 10 | # NgRx Store |
@@ -32,19 +32,24 @@ Select a store to see: |
32 | 32 | - Its kind, scope and declaring file. The file appears when the store's state keys match a `signalStore` or `signalState` in your source. |
33 | 33 | - **Store DevTools on** or **Store DevTools off**, for the classic Store. |
34 | 34 | - **Referenced by**: the component fields that hold it. |
35 | | -- **State**, **Computed** and **Methods**, with a call count per method. The tab tags `rxMethod` members. |
| 35 | +- **State**, **Computed** and **Methods**, with a call count per method. The tab tags `signalMethod` and `rxMethod` members. Once a method has been called, its chip also shows the average and last call duration, in milliseconds. |
| 36 | +- **Entities**, for a `signalStore` that calls `withEntities()`. One group per collection, with the entity count and the ids as chips. A group past 30 ids shows the first 30 and a count of the rest. |
36 | 37 |
|
37 | 38 | ### Change log |
38 | 39 |
|
39 | | -Signal stores get a **Change log**. The classic Store gets an **Action log**. Each entry shows its number, its type, the number of changes and the time. An action also shows a badge for where it came from: |
| 40 | +Signal stores get a **Change log**. The classic Store gets an **Action log**. Each entry shows its number, its type, the number of changes and the time. A method-call entry also shows how long the call itself took, and an entry whose change came from a dispatched event carries a tag with the event's type. An action also shows a badge for where it came from: |
40 | 41 |
|
41 | 42 | | Badge | Sent by | |
42 | 43 | | ---------- | ----------------------------------------------------------------------------- | |
43 | 44 | | `dispatch` | A `store.dispatch(action)` call, usually from a component or a service. | |
44 | 45 | | `effect` | An NgRx effect. Effects send their actions through `Store.next`. | |
45 | 46 | | `reactive` | `store.dispatch(() => action)`, which dispatches again when a signal changes. | |
46 | 47 |
|
47 | | -Open an entry to see its arguments, or the action and its **Origin** for the classic Store, and a **State diff** with the value before and after each change. The diff lists up to 50 changes. An action entry also has **Dispatch again**. |
| 48 | +Open an entry to see its arguments, or the action and its **Origin** for the classic Store, and a **State diff** with the value before and after each change. The diff lists up to 50 changes. A method-call entry also shows its **Duration**, in milliseconds. An entry caused by a dispatched event shows the event under **Caused by event**. An action entry also has **Dispatch again**. |
| 49 | + |
| 50 | +### Events |
| 51 | + |
| 52 | +When a page dispatches at least one `@ngrx/signals/events` event, an **Events** section lists them: the event type, its payload and the time. This section covers every store on the page, not just the selected one. Open an event to see its full payload in the same detail panel as the change log. |
48 | 53 |
|
49 | 54 | ### Dispatch an action |
50 | 55 |
|
@@ -74,12 +79,14 @@ Filter by kind with the chips. |
74 | 79 |
|
75 | 80 | ### How changes are recorded |
76 | 81 |
|
77 | | -The overlay wraps the state signals of each signal store and the store's methods. A method call becomes one log entry with its arguments. Nested method calls fold into the outer one. The overlay batches writes made outside a method and logs them as `patchState`. |
| 82 | +The overlay wraps the state signals of each signal store and the store's methods. A method call becomes one log entry with its arguments and how long the call itself took to return. That duration covers the synchronous call only, not any async work a `rxMethod` or an effect starts from it. Nested method calls fold into the outer one and do not get their own duration entry. The overlay batches writes made outside a method and logs them as `patchState`. |
78 | 83 |
|
79 | 84 | For the classic Store, the overlay listens to the dispatched actions. It also wraps `dispatch` and `next` on the Store to tag each action with its origin, and puts them back when the page disconnects. |
80 | 85 |
|
81 | 86 | The overlay diffs a copy of the state that keeps the first 100 items of each array or object. When a change is past that limit, it compares the live state instead, so the entry still lists the change. |
82 | 87 |
|
| 88 | +For `@ngrx/signals/events`, the overlay finds the platform-wide `Dispatcher` and records every event it dispatches. When a `withReducer()` case changes a tracked store's state in response, that change's log entry is tagged with the event that caused it. |
| 89 | + |
83 | 90 | ### Development builds |
84 | 91 |
|
85 | 92 | The overlay finds stores through Angular's debug API, so the live section needs a development build. |
@@ -145,6 +152,8 @@ To try another payload, type the action in **Dispatch an action** instead. |
145 | 152 | | `ng-devtools:get-ngrx-store` | tool | NgRx declarations from source, with the members of each `signalStore` and the type strings of each action. | |
146 | 153 | | `ng-devtools:dispatch-ngrx-action` | tool | Dispatches an action to the classic Store, or an action from the log again, and returns the new log entry. | |
147 | 154 | | `ng-devtools:ngrx-store` | resource | The live stores per page, with state, computeds, methods, references and the change log. Classic Store actions carry an `origin`. | |
| 155 | +| `ng-devtools:inspect-signal-store` | tool | The live state of one store, or a summary of every store discovered so far. | |
| 156 | +| `ng-devtools:signal-store-history` | tool | The live change log, oldest first: state diffs, classic `@ngrx/store` actions and `@ngrx/signals/events` events. | |
148 | 157 |
|
149 | 158 | No tool can restore a state. See [Dispatch an action](../agents/tools.md#dispatch-an-action) and [Resources](../agents/resources.md). |
150 | 159 |
|
@@ -178,6 +187,20 @@ Restore, **Back to latest**, **Dispatch** and **Dispatch again** need [`actions. |
178 | 187 |
|
179 | 188 | The log keeps the last 200 entries. Set the count with [`limits.changeLog`](../getting-started/configuration.md#limits). Once older entries are dropped, the log says how many. The overlay logs a method call that changes nothing at most once per second. |
180 | 189 |
|
| 190 | +### The selected entity is a convention, not an API |
| 191 | + |
| 192 | +`@ngrx/signals` has no built-in concept of a selected entity. The tab looks for a `selectedId` state key (or `<collection>SelectedId` for a named collection) next to a `withEntities()` collection, and shows it as **Selected** when it holds a value. A `null` or missing key shows no **Selected** row. |
| 193 | + |
| 194 | +### Events: only the platform `Dispatcher`, only synchronous reducers are tagged |
| 195 | + |
| 196 | +The overlay subscribes to the platform `Dispatcher` from `@ngrx/signals/events`. A scoped dispatcher created by a feature with its own `provideDispatcher()` is a different injectable and will not surface events here — only the root/platform dispatcher does. Switch to the platform dispatcher if you need to see those events. |
| 197 | + |
| 198 | +Each entry is tagged with its originating event (`caused by`) only when the `withReducer()` case ran synchronously inside the `Dispatcher.dispatch()` call. A `withEffects` tap or an `rxMethod` that reacts to the same event later still shows up as a plain state change — the devtools cannot tell after the fact which event caused it. |
| 199 | + |
| 200 | +### `signalMethod` vs `rxMethod` |
| 201 | + |
| 202 | +Both wrap the returned callable with a `.destroy` function, so the overlay cannot tell them apart from the live store alone. The tab reads the source scan to decide which label to show. A store with no matching declaration file (because its state keys do not line up with any `signalStore` in the scanned source) will label every reactive method as `rxMethod` by default. |
| 203 | + |
181 | 204 | ## FAQ |
182 | 205 |
|
183 | 206 | <ngmd-accordion> |
|
0 commit comments