TLDR: statestore is for overriding Node-RED config, and the updated (including dynamic updates) config is sent on the ui-config event. The datastore tracks msg objects, generally only the last received message, but can support a history of messages if required using datastore.append in the case of charts (as an example).
Server-Side Stores
Docs: State Management | Node-RED Dashboard 2.0
datastore: A map of each widget to the latestmsgreceived by a respective node in the Editor.statestore: A store for all dynamic properties set on widgets (e.g. visibility or setting a property at runtime). Often, these values are overrides of the base configuration defined in Node-RED. (This is our equivalent of FlexDash's state store.)
The pattern we've implemented in core is that the statestore is populated when a node receives messages, and detects a property in that message that it is interested in, e.g in ui-button.js:
Loading Events
Docs: Events Architecture | Node-RED Dashboard 2.0
UI Config/State
When the Dashboard is first loaded on a page refresh or navigation, we send a ui-config event, which details every widget, page, theme, etc. This contains the specification for each node (which is the Node-RED config schema), but with the relevant values overriden by the widget's statestore.
This is the single source of truth for the state of a widget at that time.
When building your own node, in the Node-RED .js file, copy the pattern seen in the buttons above. To access the stores from within a third-party node, you can call:
const group = RED.nodes.getNode(config.group)
const base = group.getBase()
base.stores.<data/state>
I don't have an example in ui-example node for dynamic properties yet, so I'll try and get something added.
Anything you put into the statestore will be merged with the config of your node and transmitted for ui-config.
Widget Load
For each widget, when that itself loads, we send a widget-load(msg) event, which passes the latest received msg from the datastore.
The widget does not need to do anything with this if it's not appropriate. The dynamic/updated state would already have been sent to the widget from the statestore via the merged ui-config schema.
Updates Required
- I had a mis-typed statement in the
statestoredescription, which claimed " Often, these values are overrides of the base configuration found in thedatastore.". This is not true, and I corrected above, it should read: "Often, these values are overrides of the base configuration defined in Node-RED. " - On my side, I do need to update the "Input" events architecture diagram to show an example of the Dynamic Properties approach we now have
Ideas for Improvement:
Alongside the msg being sent in widget-load, I could also pass the config? It's already sent with the ui-config event, but for peace of mind, it's a lightweight addition, that makes sense to include?