# Behavior traces — preactjs/preact

> Canonical page: https://codevetter.com/unpack/preact/behavior-traces

# Behavior traces — preactjs/preact

Scanned commit 45728eb4315bcb22c5d50b8fec0bbac419eaa799 (2026-10-02). Generated by codevetter codevetter 1.15.0 on 2026-10-02.

Source inspection; upstream code and tests were not executed.

The inspected flows cover initial rendering, a concrete Todo interaction, hydration, promise suspension and retry, portal rendering, and demo network loading. Each trace follows named functions across their input, state owner, and output boundary. Preact has library initialization and mounting rather than a server startup lifecycle. State retention in these flows is primarily the VNode/component graph, while the demo reads localStorage only for diagnostic switches.
- Initial mount: createElement → createVNode → render creates the Fragment root → diff selects component or element handling → diffChildren recursively reconciles output → commitRoot attaches refs and invokes callbacks. — [src/create-element.js#L16-33](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/create-element.js#L16-L33) [src/render.js#L31-58](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/render.js#L31-L58) [src/diff/index.js#L340-352](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/diff/index.js#L340-L352) [src/diff/index.js#L477-496](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/diff/index.js#L477-L496)
- Demo startup: index.html loads index.jsx → its URL check conditionally calls initDevTools/initDebug → installLogger reads localStorage/URL switches → render mounts App into document.body. — [demo/index.html#L9-12](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/demo/index.html#L9-L12) [demo/index.jsx#L31-42](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/demo/index.jsx#L31-L42) [demo/index.jsx#L192-197](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/demo/index.jsx#L192-L197)
- Todo typing: setProperty registers the input listener → eventProxy invokes setText → setText calls setState with target.value → enqueueRender schedules process → renderComponent diffs the component and commits the controlled input. — [src/diff/props.js#L72-100](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/diff/props.js#L72-L100) [src/diff/props.js#L152-170](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/diff/props.js#L152-L170) [demo/todo.jsx#L8-9](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/demo/todo.jsx#L8-L9) [src/component.js#L129-156](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/component.js#L129-L156)
- Todo addition/removal: addTodo concatenates a counter-keyed item and clears text, or removeTodo filters by data-id → setState → enqueueRender/process → TodoItems.render maps keyed li nodes → diffChildren matches/inserts or unmounts children. — [demo/todo.jsx#L12-45](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/demo/todo.jsx#L12-L45) [src/component.js#L206-253](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/component.js#L206-L253) [src/diff/children.js#L76-110](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/diff/children.js#L76-L110) [src/diff/children.js#L359-373](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/diff/children.js#L359-L373)
- Hook state update: useState delegates to useReducer → dispatch computes nextValue and compares Object.is → component.setState({}) schedules an update → options._render applies _nextValue → the component renders with its new hook value. — [hooks/src/index.js#L200-229](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/hooks/src/index.js#L200-L229) [hooks/src/index.js#L60-85](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/hooks/src/index.js#L60-L85) [src/component.js#L35-59](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/component.js#L35-L59) [src/diff/index.js#L278-286](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/diff/index.js#L278-L286)
- Hydration: hydrate sets MODE_HYDRATE → render ignores the previous VNode root and supplies existing DOM children → diffElementNodes claims matching nodes or creates missing ones → function-valued props attach handlers → commitRoot completes mounting. — [src/render.js#L21-58](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/render.js#L21-L58) [src/render.js#L69-77](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/render.js#L69-L77) [src/diff/index.js#L549-583](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/diff/index.js#L549-L583) [src/diff/index.js#L634-652](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/diff/index.js#L634-L652)
- Lazy loading: Lazy invokes loader once and throws its pending promise → diff catches and calls options._catchError → the Suspense wrapper locates _childDidSuspend → the boundary schedules fallback output → promise settlement restores parent state and force-updates suspenders. — [compat/src/suspense.js#L241-272](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/compat/src/suspense.js#L241-L272) [src/diff/index.js#L377-443](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/diff/index.js#L377-L443) [compat/src/suspense.js#L11-30](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/compat/src/suspense.js#L11-L30) [compat/src/suspense.js#L136-200](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/compat/src/suspense.js#L136-L200)
- Suspended hydration: diff records suspension flags and a start marker without discarding claimed markup → promise settlement schedules retry → diff rescans nested $s and /$s comment markers → resumed rendering removes only retained DOM it did not claim. — [src/diff/index.js#L78-108](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/diff/index.js#L78-L108) [src/diff/index.js#L361-366](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/diff/index.js#L361-L366) [src/diff/index.js#L383-430](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/diff/index.js#L383-L430) [compat/src/suspense.js#L163-200](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/compat/src/suspense.js#L163-L200)
- Portal flow: createPortal creates a Portal VNode carrying _parentDom → diff switches container and namespace, resets hydration inputs, and calls diffChildren there → it clears the portal's host _dom and restores the host insertion cursor. — [src/create-portal.js#L9-19](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/create-portal.js#L9-L19) [src/diff/index.js#L309-358](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/diff/index.js#L309-L358)
- People loading/navigation: App.componentDidMount → store.loadUsers → fetch/json/map → users.replace → observer render generates profile links → Link.handleClick → Router.navigate/history.pushState → nested Route renders Profile. — [demo/people/index.tsx#L9-53](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/demo/people/index.tsx#L9-L53) [demo/people/store.ts#L47-58](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/demo/people/store.ts#L47-L58) [demo/people/router.tsx#L39-96](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/demo/people/router.tsx#L39-L96) [demo/people/router.tsx#L130-150](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/demo/people/router.tsx#L130-L150)
- Unmount: render(null, container) removes unmatched children → unmount invokes options.unmount, ref cleanup, and componentWillUnmount → it recursively removes DOM and clears ownership/listeners; hooks defer passive cleanup through their after-paint queue. — [compat/src/index.js#L104-109](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/compat/src/index.js#L104-L109) [src/diff/children.js#L359-373](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/diff/children.js#L359-L373) [src/diff/index.js#L755-796](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/src/diff/index.js#L755-L796) [hooks/src/index.js#L127-160](https://github.com/preactjs/preact/blob/45728eb4315bcb22c5d50b8fec0bbac419eaa799/hooks/src/index.js#L127-L160)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
