@@ -130,16 +130,6 @@ def _create_layout_update(self, component: AbstractComponent) -> LayoutUpdate:
130
130
self ._render_component (old_state , new_state , component )
131
131
changes = make_patch (getattr (old_state , "model" , {}), new_state .model ).patch
132
132
133
- # replace model and state in parent
134
- if hasattr (new_state , "parent_ref" ):
135
- parent = new_state .parent_ref ()
136
- if parent is not None :
137
- parent .children_by_key [new_state .key ] = new_state
138
- parent .model ["children" ][new_state .index ] = new_state .model
139
-
140
- # replace in global state
141
- self ._model_state_by_component_id [id (component )] = new_state
142
-
143
133
# hook effects must run after the update is complete
144
134
for state in new_state .iter_children ():
145
135
if hasattr (state , "life_cycle_hook" ):
@@ -166,6 +156,26 @@ def _render_component(
166
156
logger .exception (f"Failed to render { component } " )
167
157
new_state .model = {"tagName" : "__error__" , "children" : [str (error )]}
168
158
159
+ if old_state is not None and old_state .component is not component :
160
+ del self ._model_state_by_component_id [id (old_state .component )]
161
+ self ._model_state_by_component_id [id (component )] = new_state
162
+
163
+ try :
164
+ parent = new_state .parent
165
+ except AttributeError :
166
+ pass
167
+ else :
168
+ key , index = new_state .key , new_state .index
169
+ if old_state is not None :
170
+ assert (key , index ) == (old_state .key , old_state .index ,), (
171
+ "state mismatch during component update - "
172
+ f"key { key !r} !={ old_state .key } "
173
+ f"or index { index } !={ old_state .index } "
174
+ )
175
+ parent .children_by_key [key ] = new_state
176
+ # need to do insertion in case where old_state is None and we're appending
177
+ parent .model ["children" ][index : index + 1 ] = [new_state .model ]
178
+
169
179
def _render_model (
170
180
self ,
171
181
old_state : Optional [_ModelState ],
@@ -259,8 +269,8 @@ def _render_model_children(
259
269
else :
260
270
child = str (child )
261
271
child_type = STRING_TYPE
262
- # The key doesn't matter since we won't look it up - all that matter is
263
- # that the key is unique ( which this approach guarantees)
272
+ # The specific key doesn't matter here since we won't look it up - all
273
+ # we care about is that the key is unique, which object() can guarantee.
264
274
key = object ()
265
275
raw_typed_children_by_key [key ] = (child_type , child )
266
276
@@ -288,16 +298,11 @@ def _render_model_children(
288
298
elif child_type is COMPONENT_TYPE :
289
299
old_child_state = old_state .children_by_key .get (key )
290
300
if old_child_state is not None :
291
- old_component = old_child_state .life_cycle_hook .component
292
- del self ._model_state_by_component_id [id (old_component )]
293
301
new_child_state = old_child_state .new (new_state , child )
294
302
else :
295
303
hook = LifeCycleHook (child , self )
296
304
new_child_state = _ModelState (new_state , index , key , hook )
297
305
self ._render_component (old_child_state , new_child_state , child )
298
- new_children .append (new_child_state .model )
299
- new_state .children_by_key [key ] = new_child_state
300
- self ._model_state_by_component_id [id (child )] = new_child_state
301
306
else :
302
307
new_children .append (child )
303
308
@@ -317,9 +322,6 @@ def _render_model_children_without_old_state(
317
322
life_cycle_hook = LifeCycleHook (child , self )
318
323
child_state = _ModelState (new_state , index , key , life_cycle_hook )
319
324
self ._render_component (None , child_state , child )
320
- new_children .append (child_state .model )
321
- new_state .children_by_key [key ] = child_state
322
- self ._model_state_by_component_id [id (child )] = child_state
323
325
else :
324
326
new_children .append (str (child ))
325
327
@@ -344,6 +346,7 @@ class _ModelState:
344
346
"key" ,
345
347
"_parent_ref" ,
346
348
"life_cycle_hook" ,
349
+ "component" ,
347
350
"patch_path" ,
348
351
"key_path" ,
349
352
"model" ,
@@ -373,6 +376,7 @@ def __init__(
373
376
374
377
if life_cycle_hook is not None :
375
378
self .life_cycle_hook = life_cycle_hook
379
+ self .component = life_cycle_hook .component
376
380
377
381
self .event_targets : Set [str ] = set ()
378
382
self .children_by_key : Dict [str , _ModelState ] = {}
0 commit comments