# How to sync the FULL config between server and client side state

**URL:** <https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252>\
**Category:** Dashboard\
**Tags:** flexdash, dashboard-2\
**Created:** [4 July 2024 05:55 UTC](https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252 "2024-07-04T05:55:31Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)\
**Post date:** [4 July 2024 05:55 UTC](https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252/1 "2024-07-04T05:55:31Z")

</div>

Hi folks,

In the old AngularJs dashboard there was a mechanism called _ **msg replay** _, which meant that the last input message was send again to the client side widget (e.g. when the browser page was refreshed). That way you could reconfigure your widget again, to match the last state stored in that last input message.

While that sounded at first a very brilliant idea, it resulted in a tremendous headache for ui node developers. For the simple reason that _ **the last message only contains a small fraction of the widget full state** _. Let's explain this by a hypothetical button example:

1. Message is injected to change the button label.
2. Message is injected to change the button color.
3. The browser page is refreshed.
4. The last messages is resend, so you set the correct button color. However you don't have the correct button label, because the last message contains only a part of the state (i.e. the last message only the color, but not the label).

Thorsten had solved that in Flexdash, by having _messages updating a server-side state and sending the delta state to the clients (to update the client-side state to keep it in sync with the server-side state)_. Same hypothetical button example:

1. Message is injected to change the button label.
2. The server-side state is updated with the new label and the new label is send to the clients, which update their client-side state with the new label.
3. Message is injected to change the button color.
4. The server-side state is updated with the new color, and the new color is send to the clients, which update their client-side state with the new color. Both server-side and client-side states are in sync and contain the FULL state.
5. The browser page is refreshed.
6. The server-side is resend, so the client-side state is correctly updated with both the new label and the new color.

For my old AngularJs ui-svg node it was the worst. For example in a floorplan you visualize a lot of devices, so a lot of state updates are required. Users had to find their own workarounds, e.g. by replaying a queue of N messages. But that is totally not waterproof, because:

- If N is not large enough, then you loose old state updates.
- The queue contains lot of messages overriding each other values over time (e.g. color red -\> color green -\> color red -\> color green -\> ...).
- Very inefficient to replay lots of old message, containing most of the time obsolete state.

In an attempt to avoid a new message replay mechanism in the new dashboard, I have at the time being tried to explain this problem in this [issue](https://github.com/FlowFuse/node-red-dashboard/issues/61). However the message based approach has been reintroduced again, so unfortunately I am completely stuck again.

So I starting rereading the documentation again, to see if there is a way to solve my issue. But not sure how I can workaround it when reading [this](https://dashboard.flowfuse.com/contributing/guides/state-management.html#data-store) part of the documentation:

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/b/3/b3548ac4e4acbec226684e8cc7bcd3bb2b8217f8.png)

I think I have overlooked something. Because the statement _in most cases a widget only needs reference to the last message_ only makes sense when that last message contains the full state. I read somewhere in the documentation that the (recently introduced) dynamic properties are being merged automatically into the static properties from the config screen. So perhaps that is a new dashboard change to improve the message replay mechanism? Perhaps the keyword "message" in the client-side context is referring to messages from server to client, and not the input messages of the ui node? No idea...

Would appreciate a lot if somebody could enlighten me! Because I don't see the overal picture anymore.

Thanks!!  
Bart

---

<div class="post-metadata">

**Author:** ![joepavitt](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/joepavitt/32/59722_2.png) [@joepavitt](https://discourse.nodered.org/u/joepavitt)\
**Post date:** [4 July 2024 06:40 UTC](https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252/2 "2024-07-04T06:40:39Z")

</div>

I have to confess - read through this, I'm now confused myself. Will zip through relevant docs and codebase and make sure i present a clear picture of what's going on.

I do believe though, that, as you say, we have the shortfall of last `msg` being replayed rather than an accumulative state per FlexDash - always open to change/iteration though, and it wouldn't be too much of a breaking change (if at all) to introduce this instead

---

<div class="post-metadata">

**Author:** ![omrid](https://avatars.discourse-cdn.com/v4/letter/o/77aa72/32.png) [@omrid](https://discourse.nodered.org/u/omrid)\
**Post date:** [4 July 2024 07:13 UTC](https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252/3 "2024-07-04T07:13:15Z")

</div>

Adding my $0.02:  
I believe we should not be saving msg sequences, as some messages represent actions, not data updates, and you would not want to replay these. For example, you may want to periodically send a message to your node telling it to email its data, and you do not want to replay this upon reload.

IMHO, the datastore should maintain a data image which enables the node to restore itself upon open/refresh, and look the same as in other clients. This data image can also include history (e.g. for a chart - an array of data updates), but in any case this would be a node-specific implementation, not generic blind replay of messages.

---

<div class="post-metadata">

**Author:** ![joepavitt](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/joepavitt/32/59722_2.png) [@joepavitt](https://discourse.nodered.org/u/joepavitt)\
**Post date:** [4 July 2024 07:15 UTC](https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252/4 "2024-07-04T07:15:56Z")

</div>

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](https://dashboard.flowfuse.com/contributing/guides/state-management.html#server-side-node-red)

- `datastore`: A map of each widget to the latest `msg` received 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`:

> <https://github.com/FlowFuse/node-red-dashboard/blob/a2b791cdd43bb78b04b5197c06f8923c28da329f/nodes/widgets/ui_button.js#L47-L65>

### Loading Events

Docs: [Events Architecture | Node-RED Dashboard 2.0](https://dashboard.flowfuse.com/contributing/guides/events.html#loading-event-flow)

#### 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:

```auto
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 `statestore` description, which claimed _" Often, these values are overrides of the base configuration found in the `datastore`."_. 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](https://dashboard.flowfuse.com/contributing/guides/events.html#input-event-flow) 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?

---

<div class="post-metadata">

**Author:** ![omrid](https://avatars.discourse-cdn.com/v4/letter/o/77aa72/32.png) [@omrid](https://discourse.nodered.org/u/omrid)\
**Post date:** [4 July 2024 07:25 UTC](https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252/5 "2024-07-04T07:25:19Z")

</div>

> [@joepavitt](#):
>
> #### 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`.

Taking the opportunity to remind that the on-widget event should be sent (with an empty message) even when there is no data in the datastore ("no data" is also data).

> [@joepavitt](#):
>
> ### 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?

Are you referring to the node's config object with the configured node properties? Is it different than what is uploaded into the `this.props` object?

---

<div class="post-metadata">

**Author:** ![joepavitt](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/joepavitt/32/59722_2.png) [@joepavitt](https://discourse.nodered.org/u/joepavitt)\
**Post date:** [4 July 2024 07:42 UTC](https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252/6 "2024-07-04T07:42:11Z")

</div>

> [@omrid](#):
>
> Are you referring to the node's config object with the configured node properties? Is it different than what is uploaded into the `this.props` object?

They are the same. `this.props` was poor variable naming on my part, that, to change now would cause _a lot_ of breaking changes

---

<div class="post-metadata">

**Author:** ![dceejay](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dceejay/32/38_2.png) [@dceejay](https://discourse.nodered.org/u/dceejay)\
**Post date:** [4 July 2024 08:18 UTC](https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252/7 "2024-07-04T08:18:18Z")

</div>

On the original D1 dashboard the replay was only for the payload part of the msg, as a) that was the original design and the concept of allowing dynamic update of things like labels was only added much later, and b) extending it to the whole msg would potentially mean storing masses of data - (or how would you select which properties to store, etc)

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [4 July 2024 10:08 UTC](https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252/8 "2024-07-04T10:08:18Z")

</div>

> [@joepavitt](#):
>
> 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).

In third party nodes, at least, I do not believe that is necessarily the case. What is stored in the datastore is entirely up to the developer. In the example node `nodes/ui-example.js` the onInput function is

```auto
            onInput: function (msg, send, done) {
                // store the latest value in our Node-RED datastore
                base.stores.data.save(base, node, msg)
                // send it to any connected nodes in Node-RED
                send(msg)
            },

```

This stores the latest message in the store and then sends it to the client, so the store does contain the last message, and when a node connects only that latest message is sent to the node.

In my nodes I have not done that, I use the datastore as a store for the complete state of the widget. My classic gauge node, for example, requires current values for each needle, but those values arrive individually, identified by topic. When a needle value is received I update the value for that needle in the store, and then send the original message to the client.  
When a client connects it gets sent the datastore, which contains the full state and saves that locally. When a new message is received, for example with a needle value, it updates that needle value in its local store. The result is that the server and client always have a full copy of the state. So far this technique is working well for me and is very simple to understand and implement. So far I am not aware of any issues with using this simple system.

Edit: I have made a slight amendment to the above, adding the word 'original' for clarification in the sentence 'When a needle value is received I update the value for that needle in the store, and then send the _original_ message to the client'.

---

<div class="post-metadata">

**Author:** ![joepavitt](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/joepavitt/32/59722_2.png) [@joepavitt](https://discourse.nodered.org/u/joepavitt)\
**Post date:** [4 July 2024 10:51 UTC](https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252/9 "2024-07-04T10:51:23Z")

</div>

Yep, good point - I can't control what people do in their third-party nodes. I've built in the APIs to copy core patterns, but if devs want to go off-piste, then that's fine too

---

<div class="post-metadata">

**Author:** ![arturv2000](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/arturv2000/32/88724_2.png) [@arturv2000](https://discourse.nodered.org/u/arturv2000)\
**Post date:** [4 July 2024 10:57 UTC](https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252/10 "2024-07-04T10:57:01Z")

</div>

> [@joepavitt](#):
>
> #### 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.

The second part is only true if the application is a single page/Tab. If we have several tabs and are visualizing another tab, all the configuration that had been sent to the widget will be lost (except the last one) when we return the tab where the widget is (no reload, just switching tabs).

> [@joepavitt](#):
>
> ### 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?

This is related to a an PR I have open, in that case related to UI-Button but it is applicable to all widgets. One of the changes was in the `widget-load` event adding to the message all the Dynamic Properties that have been received for that Widget, in order to restore the widget to the correct state even if it had received several separated messages each one with one Dynamic Property set...

For this to work is also necessary to add a `onLoad` event in the widget itself, some of them only have the `onDynamicProperties` event which is not triggered on `widget-load`.

The is also the necessity to also sync other things that are not the dynamic properties, like the `enable`, `class` and `visible`, depending on the widget may be more, that at the moment with the latest updates are not part of `Dynamic Propreties` and are left a little in the limbo. These properties should pass to the `Dynamic Properties` (`ui_update`) group, at least the `enable` that is applicable to the widget itself, `class` and `visible` seems more to the `nrdb-ui-widget` (row element) than the widget (button) itself.

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [4 July 2024 11:08 UTC](https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252/11 "2024-07-04T11:08:08Z")

</div>

> [@joepavitt](#):
>
> if devs want to go off-piste, then that's fine too

Do you see any issues with my strategy, which to me seems much simpler than the core pattern? For example, in the chart node, I assume that the state store retains an array of a (potentially) large number of previous messages so that the client can build the chart on initial connection. Would it not be much simpler to understand if the server just maintained a copy of the current state of the chart?

Similarly with the issue @arturv2000 notes regarding `enable` etc. If those are maintained as part of the state in the server then the problem is solved.

---

<div class="post-metadata">

**Author:** ![joepavitt](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/joepavitt/32/59722_2.png) [@joepavitt](https://discourse.nodered.org/u/joepavitt)\
**Post date:** [4 July 2024 12:11 UTC](https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252/12 "2024-07-04T12:11:26Z")

</div>

> [@arturv2000](#):
>
> If we have several tabs and are visualizing another tab, all the configuration that had been sent to the widget will be lost (except the last one) when we return the tab where the widget is (no reload, just switching tabs).

That's valid, which is why I propose including `config` inside `widget-load` event

---

<div class="post-metadata">

**Author:** ![joepavitt](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/joepavitt/32/59722_2.png) [@joepavitt](https://discourse.nodered.org/u/joepavitt)\
**Post date:** [4 July 2024 12:12 UTC](https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252/13 "2024-07-04T12:12:17Z")

</div>

> [@arturv2000](#):
>
> that at the moment with the latest updates are not part of `Dynamic Propreties` and are left a little in the limbo.

Yes, it's a difficult one as I need to handle backward compatibility, whilst also offering improvements to the API

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [4 July 2024 13:00 UTC](https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252/14 "2024-07-04T13:00:10Z")

</div>

I have just re-read the earlier posts again and realised that the statestore is actually being used in the way that I have used the datastore, so in fact I should put all my dynamic properties (such as gauge needle current values) into the statestore, not the datastore. I think that means that actually I don't have any need for the datastore. In fact I am not sure why it is needed at all.

With ui\_update data, in a third party node, will ui\_update values automatically get included in the statestore, overriding the config, or do I need to handle that myself?

---

<div class="post-metadata">

**Author:** ![joepavitt](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/joepavitt/32/59722_2.png) [@joepavitt](https://discourse.nodered.org/u/joepavitt)\
**Post date:** [4 July 2024 13:20 UTC](https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252/15 "2024-07-04T13:20:06Z")

</div>

> [@Colin](#):
>
> I think that means that actually I don't have any need for the statestore. In fact I am not sure why it is needed at all

I _think_ you mean `datastore` here, as you just mentioned you'd be switching stuff _too_ the `statestore`.

The `datastore` is still needed because in multi-tenant use cases, when we replay messages, how do we know who should receive that message? We need the full `msg` context to be sure of this.

I'd separated out `state` and `data` intentionall, where `state` defines anything in the node's configuration, the `data` is the latest `msg` objects, and generally useful to access `msg.payload`, but not limited to.

> [@Colin](#):
>
> With ui\_update data, in a third party node, will ui\_update values automatically get included in the statestore, overriding the config, or do I need to handle that myself?

It's a practice we've implemented, up to third-party devs to follow suit, or do their own thing

---

<div class="post-metadata">

**Author:** ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)\
**Post date:** [4 July 2024 21:12 UTC](https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252/16 "2024-07-04T21:12:47Z")

</div>

Ok, thanks everybody!  
Will try to digest the great feedback from everybody this weekend.  
I went back to the drawing table, and indeed it looks quite how I had the Flexdash setup in my mind. More as I had expected to be honest.  
I need to read again through some other discussion (like e.g. the one I had last week with @Colin about his experience), and then I will get back here.  
I need to visualize it in a diagram, to allow my brain to understand all of it...

---

<div class="post-metadata">

**Author:** ![Colin](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/colin/32/17040_2.png) [@Colin](https://discourse.nodered.org/u/Colin)\
**Post date:** [4 July 2024 21:23 UTC](https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252/17 "2024-07-04T21:23:56Z")

</div>

> [@joepavitt](#):
>
> > [@Colin](#):
> >
> > I think that means that actually I don't have any need for the statestore. In fact I am not sure why it is needed at all
> 
> I _think_ you mean `datastore` here, as you just mentioned you'd be switching stuff _too_ the `statestore`.

Yes indeed, thanks, I have corrected my post.

> [@joepavitt](#):
>
> The `datastore` is still needed because in multi-tenant use cases, when we replay messages, how do we know who should receive that message? We need the full `msg` context to be sure of this.

Is the latest message saved for each user in the multi-tenant case? Otherwise it doesn't really work does it? Only one user will have a message to be replayed.

---

<div class="post-metadata">

**Author:** ![Buckskin](https://avatars.discourse-cdn.com/v4/letter/b/b9e5f3/32.png) [@Buckskin](https://discourse.nodered.org/u/Buckskin)\
**Post date:** [4 July 2024 21:57 UTC](https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252/18 "2024-07-04T21:57:54Z")

</div>

This question probably implies a lack of understanding on my part. I understand this is about pre-built widgets but I was wondering if any of this is / can be utilised in a ui-template widget?

---

<div class="post-metadata">

**Author:** ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)\
**Post date:** [5 July 2024 06:08 UTC](https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252/19 "2024-07-05T06:08:25Z")

</div>

> [@BartButenaers](#):
>
> Will try to digest the great feedback from everybody this weekend.

I created quickly a first DRAFT version, and share it now already because I have still a lot of questions in RED. If somebody can answer some of those, that would be nice:

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/b/b/bbd2733d008525b419eeb9626d1baae464afef6b.png)

Some general remarks:

1. I "think" that I was partly confused because the full state of a widget is called also "msg" in the frontend, but not sure.
2. When a message is loaded then the last input msg is being replayed. Imho I certainly would not add extra parameters to the on-load event, but skip the input msg from that event completely. Because that msg:
  - Contains only partial state, so that is looking for troubles.
  - Mixing in the frontend state that arrives from input messages and from the servers-side stores is VERY confusing.

3. Like @Colin mentioned, it is not clear to me how you support multi-tenant stuff by replaying only the last input message, containing partial state.
4. Lots more questions in my drawing.

If anybody wants to draw on top of my drawing in Paint, be my guest. I will adjust my drawing with the feedback during the weekend.

Thanks!!!!!!!!!!!!!!!

---

<div class="post-metadata">

**Author:** ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)\
**Post date:** [5 July 2024 14:47 UTC](https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252/20 "2024-07-05T14:47:58Z")

</div>

Following my diagram, I will try to avoid using the _ **Data store** _ at all cost.

So I want to store my dynamic properties (from `msg.ui_update`) into the _ **State store** _. However that fails, because only the Data store seems to be available:

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/2/0/209e853729a689ad4b6118be34637e1d2c162080.png)

_ **EDIT:** _ I have registered a Github [issue](https://github.com/FlowFuse/node-red-dashboard/issues/1067) and will try to solve it this weekend.

[Next page](https://discourse.nodered.org/t/how-to-sync-the-full-config-between-server-and-client-side-state/89252.md?page=2)
