(
self,
exit_stack: AsyncExitStack,
old_state: _ModelState | None,
new_state: _ModelState,
component: ComponentType,
)
| 176 | } |
| 177 | |
| 178 | async def _render_component( |
| 179 | self, |
| 180 | exit_stack: AsyncExitStack, |
| 181 | old_state: _ModelState | None, |
| 182 | new_state: _ModelState, |
| 183 | component: ComponentType, |
| 184 | ) -> None: |
| 185 | life_cycle_state = new_state.life_cycle_state |
| 186 | life_cycle_hook = life_cycle_state.hook |
| 187 | |
| 188 | self._model_states_by_life_cycle_state_id[life_cycle_state.id] = new_state |
| 189 | |
| 190 | await life_cycle_hook.affect_component_will_render(component) |
| 191 | exit_stack.push_async_callback(life_cycle_hook.affect_layout_did_render) |
| 192 | try: |
| 193 | raw_model = component.render() |
| 194 | # wrap the model in a fragment (i.e. tagName="") to ensure components have |
| 195 | # a separate node in the model state tree. This could be removed if this |
| 196 | # components are given a node in the tree some other way |
| 197 | wrapper_model: VdomDict = {"tagName": "", "children": [raw_model]} |
| 198 | await self._render_model(exit_stack, old_state, new_state, wrapper_model) |
| 199 | except Exception as error: |
| 200 | logger.exception(f"Failed to render {component}") |
| 201 | new_state.model.current = { |
| 202 | "tagName": "", |
| 203 | "error": ( |
| 204 | f"{type(error).__name__}: {error}" |
| 205 | if REACTPY_DEBUG_MODE.current |
| 206 | else "" |
| 207 | ), |
| 208 | } |
| 209 | finally: |
| 210 | await life_cycle_hook.affect_component_did_render() |
| 211 | |
| 212 | try: |
| 213 | parent = new_state.parent |
| 214 | except AttributeError: |
| 215 | pass # only happens for root component |
| 216 | else: |
| 217 | key, index = new_state.key, new_state.index |
| 218 | parent.children_by_key[key] = new_state |
| 219 | # need to add this model to parent's children without mutating parent model |
| 220 | old_parent_model = parent.model.current |
| 221 | old_parent_children = old_parent_model["children"] |
| 222 | parent.model.current = { |
| 223 | **old_parent_model, |
| 224 | "children": [ |
| 225 | *old_parent_children[:index], |
| 226 | new_state.model.current, |
| 227 | *old_parent_children[index + 1 :], |
| 228 | ], |
| 229 | } |
| 230 | |
| 231 | async def _render_model( |
| 232 | self, |
no test coverage detected