@@ -101,22 +101,36 @@ async def _element_states(self) -> AsyncIterator[ElementState]:
101101 try :
102102 yield {self ._root .id : root_element_state }
103103 finally :
104- self ._unmount_element_state (root_element_state )
104+ self ._delete_element_state (root_element_state )
105105
106106 async def _create_layout_update (self , element : AbstractElement ) -> LayoutUpdate :
107107 element_state = self ._element_states [element .id ]
108+
109+ element_state .life_cycle_hook .element_will_render ()
110+
111+ for state in self ._iter_element_states_from_root (
112+ element_state ,
113+ include_root = False ,
114+ ):
115+ state .life_cycle_hook .element_will_unmount ()
116+
117+ self ._clear_element_state_event_handlers (element_state )
118+ self ._delete_element_state_children (element_state )
119+
108120 old_model = element_state .model .copy () # we copy because it will be mutated
109121 new_model = await self ._render_element (element_state )
110122 changes = make_patch (old_model , new_model ).patch
123+
124+ for state in self ._iter_element_states_from_root (
125+ element_state ,
126+ include_root = True ,
127+ ):
128+ state .life_cycle_hook .element_did_render ()
129+
111130 return LayoutUpdate (path = element_state .path , changes = changes )
112131
113132 async def _render_element (self , element_state : ElementState ) -> Dict [str , Any ]:
114133 try :
115- element_state .life_cycle_hook .element_will_render ()
116-
117- self ._clear_element_state_event_handlers (element_state )
118- self ._unmount_element_state_children (element_state )
119-
120134 # BUG: https://github.com/python/mypy/issues/9256
121135 raw_model = await _render_with_life_cycle_hook (element_state ) # type: ignore
122136
@@ -126,8 +140,6 @@ async def _render_element(self, element_state: ElementState) -> Dict[str, Any]:
126140 resolved_model = await self ._render_model (element_state , raw_model )
127141 element_state .model .clear ()
128142 element_state .model .update (resolved_model )
129-
130- element_state .life_cycle_hook .element_did_render ()
131143 except Exception :
132144 logger .exception (f"Failed to render { element_state .element_obj } " )
133145
@@ -206,24 +218,43 @@ def _create_element_state(
206218
207219 def _reset_element_state (self , element_state : ElementState ) -> None :
208220 self ._clear_element_state_event_handlers (element_state )
209- self ._unmount_element_state_children (element_state )
221+ self ._delete_element_state_children (element_state )
210222
211- def _unmount_element_state (self , element_state : ElementState ) -> None :
212- element_state .life_cycle_hook .element_will_unmount ()
223+ def _delete_element_state (self , element_state : ElementState ) -> None :
213224 self ._clear_element_state_event_handlers (element_state )
214- self ._unmount_element_state_children (element_state )
225+ self ._delete_element_state_children (element_state )
215226 del self ._element_states [element_state .element_obj .id ]
216227
217228 def _clear_element_state_event_handlers (self , element_state : ElementState ) -> None :
218229 for handler_id in element_state .event_handler_ids :
219230 del self ._event_handlers [handler_id ]
220231 element_state .event_handler_ids .clear ()
221232
222- def _unmount_element_state_children (self , element_state : ElementState ) -> None :
233+ def _delete_element_state_children (self , element_state : ElementState ) -> None :
223234 for e_id in element_state .child_elements_ids :
224- self ._unmount_element_state (self ._element_states [e_id ])
235+ self ._delete_element_state (self ._element_states [e_id ])
225236 element_state .child_elements_ids .clear ()
226237
238+ def _iter_element_states_from_root (
239+ self ,
240+ root_element_state : ElementState ,
241+ include_root : bool ,
242+ ) -> Iterator [ElementState ]:
243+ if include_root :
244+ pending = [root_element_state ]
245+ else :
246+ pending = [
247+ self ._element_states [i ] for i in root_element_state .child_elements_ids
248+ ]
249+
250+ while pending :
251+ visited_element_state = pending .pop (0 )
252+ yield visited_element_state
253+ pending .extend (
254+ self ._element_states [i ]
255+ for i in visited_element_state .child_elements_ids
256+ )
257+
227258
228259@coroutine
229260def _render_with_life_cycle_hook (element_state : ElementState ) -> Iterator [None ]:
0 commit comments