Skip to content

Commit 3488996

Browse files
fix(widgets): reconcile widget store entry when widget type changes
registerWidget returned the existing store entry unconditionally, so when a subgraph convert reused a graphId:nodeId:name key for a different widget, the stale entry won and the widget rendered with the wrong type (a multiline text widget showed as an int widget until a page reload rehydrated the store). Keep the idempotent return only when the existing entry's type matches; on a type mismatch the id now belongs to a different widget, so overwrite with the live type and value. Same-type re-registration still preserves edited values. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent cec0554 commit 3488996

2 files changed

Lines changed: 18 additions & 1 deletion

File tree

src/stores/widgetValueStore.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,21 @@ describe('useWidgetValueStore', () => {
112112
expect(second.value).toBe(99)
113113
})
114114

115+
it('replaces a stale entry when the widget type changes', () => {
116+
const store = useWidgetValueStore()
117+
const first = store.registerWidget(seedA, state('number', 5))!
118+
first.value = 42
119+
120+
// After a subgraph convert the graphId:nodeId:name key can be reused by a
121+
// different widget. A type mismatch means it is not the same widget, so
122+
// the live type/value must win rather than the stale entry (BUG: a text
123+
// widget rendered as int until reload).
124+
const reconciled = store.registerWidget(seedA, state('string', 'hello'))!
125+
expect(reconciled.type).toBe('string')
126+
expect(reconciled.value).toBe('hello')
127+
expect(store.getWidget(seedA)?.type).toBe('string')
128+
})
129+
115130
it('registers a widget with all properties', () => {
116131
const store = useWidgetValueStore()
117132
const registered = store.registerWidget(

src/stores/widgetValueStore.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ export const useWidgetValueStore = defineStore('widgetValue', () => {
3131
if (!isWidgetId(widgetId)) return undefined
3232

3333
const existing = getWidget(widgetId)
34-
if (existing) return existing as WidgetState<TValue>
34+
if (existing && existing.type === init.type) {
35+
return existing as WidgetState<TValue>
36+
}
3537

3638
const { graphId, nodeId, name } = parseWidgetId(widgetId)
3739
const state: WidgetState<TValue> = {

0 commit comments

Comments
 (0)