원클릭으로
preact-options-hooks
Preact guidelines to use the global options hooks for extending preact.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Preact guidelines to use the global options hooks for extending preact.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Use when hardening npm package release workflows with trusted publishing, OIDC, GitHub environments, pinned GitHub Actions, disabled publish-path caching, Changesets release PRs, direct tag-based npm publish flows, staged publishing, or npm release-supply-chain reviews.
Use when migrating React code or libraries to Preact, configuring preact/compat, bundler aliases, react/jsx-runtime, react-dom, Jest, Node SSR aliases, or diagnosing duplicate React/Preact copies and compat behavior differences.
Use when enabling preact/debug, interpreting Preact debug warnings, invalid HTML nesting or table parser problems, hydration mismatch diagnostics, duplicate keys, invalid refs/events, or component stack traces.
Use when building or debugging Preact forms, controlled or uncontrolled inputs, onInput versus onChange, checkbox, radio, select, textarea behavior, hydration of form state, cursor preservation, or compat event normalization.
Use when Preact hooks fail with invalid hook calls, __H undefined or null errors, mixed CJS/ESM imports, no-build import maps, duplicate Preact copies, useId SSR mismatches, or effect scheduling problems.
Use when Preact SSR, prerendering, hydrate(), Suspense, lazy, streaming SSR, renderToStringAsync(), or browser-parsed HTML produces hydration warnings, duplicate nodes, mismatched DOM, lost focus, stale fallback markup, or client-only conditional render bugs.
| name | preact-options-hooks |
| description | Preact guidelines to use the global options hooks for extending preact. |
Preact exposes a mutable options object (import { options } from 'preact') that acts as a global hook system into the rendering pipeline. Any tool, library, or devtool can monkey-patch these hooks to observe or intercept every phase of the diff/commit cycle — no fibers, no DevTools protocol, no bippy.
Always save the previous value before overwriting so other plugins (and Preact's own debug addon) keep working:
import { options } from 'preact';
const prev = options.diffed;
options.diffed = (vnode) => {
// your logic
prev?.(vnode);
};
To unhook, never restore the saved reference as other plugins might get lost. Instead, use a bail flag so the options chain stays intact:
let active = true;
const prev = options.diffed;
options.diffed = (vnode) => {
if (active) {
// your logic
}
prev?.(vnode);
};
// To stop observing without breaking other plugins:
active = false;
During a single render cycle the hooks fire in this order:
| Hook | Mangled name | Fires when | Signature |
|---|---|---|---|
| before-diff | options.__b | Just before a VNode starts diffing (called for every VNode, host and component). Good place to detect start of a commit batch. | (vnode: VNode) => void |
| before-render | options.__r | Immediately before a component VNode's render() / function body executes. Best place to start a performance timer. | (vnode: VNode) => void |
| diffed | options.diffed | After a VNode (and all its children) have been diffed. The DOM is updated at this point. Best place to stop a timer and read the resulting DOM. | (vnode: VNode) => void |
| commit | options.__c | After the entire tree's diff is done and the commit queue is about to flush (lifecycle methods / effects). Signals end of a commit batch. | (vnode: VNode, commitQueue: Component[]) => void |
| unmount | options.unmount | Before a VNode is removed from the tree. | (vnode: VNode) => void |
| hook | options.__h | When a hook (useState, useEffect, etc.) is invoked inside a component. hookType is an integer identifying the hook kind. | (component: Component, index: number, hookType: number) => void |
| Hook | Mangled name | Purpose |
|---|---|---|
options.vnode | options.vnode | Called when a VNode is created (createElement / JSX). Can mutate the vnode. |
options.event | options.event | Called before DOM events are processed. |
options.debounceRendering | options.debounceRendering | Called so renders can be batched, by default this is queueMicrotask. |
Preact 10.x mangles internal properties. The key ones on a VNode:
| Property | Mangled | Type | Meaning |
|---|---|---|---|
| component | __c | Component | null | The class/function component instance |
| dom | __e | Element | Text | null | First DOM node produced by this VNode |
| children | __k | VNode[] | null | Child VNodes |
| parent | __ | VNode | null | Parent VNode |
| flags | __b | number | Internal diff flags / start offset |
| index | __i | number | Index in parent's children array |
Specifically for flags, they have a certain bit-wise meaning, where 1<<7 means that the vnode is suspended and 1<<5 means that the node is hydrating.
| Property | Mangled | Type | Meaning |
|---|---|---|---|
| vnode | __v | VNode | The VNode this component rendered |
| nextState | __s | object | Pending state (before commit) |
| dirty | __d | boolean | Whether component is queued for re-render |
| force | __f | boolean | Whether forceUpdate() was called |
| hooks | __H | { __: HookState[], __h: HookState[] } | null | Hooks state container. __ is the ordered list; __h is pending effects. |
Each HookState has __ (the current value) and __H (deps array, if applicable).
function getDisplayName(vnode) {
const type = vnode.type;
if (typeof type === 'string') return null; // host element like 'div'
if (typeof type === 'function') {
return type.displayName || type.name || null;
}
return null;
}
A component VNode's __e may be null (fragments, Providers, etc.). Walk the child VNode list:
function getDOMNode(vnode) {
if (vnode.__e instanceof Element) return vnode.__e;
for (const child of vnode.__k || []) {
if (child?.__e instanceof Element) return child.__e;
}
return null;
}
A component is mounting if there is no previous props snapshot / no alternate. The simplest approach: track whether you've seen the component instance before (e.g., via a WeakMap or a custom property on the vnode.__c).
options.__b fires for every VNode in a diff pass. The first call marks the start of a commit. options.__c fires once at the end with the full commit queue. This lets you implement onCommitStart / onCommitFinish semantics.
options.__b fires for all VNodes (host elements too), not just components. Filter with typeof vnode.type === 'function' when you only care about components, string for dom-nodes or null for text-nodes.__b, __r, __c, __h, __e, etc.) are stable across Preact 10.x and are the canonical way to access internals — Preact's own addons (preact/debug, preact/devtools) use them.options.diffed fires bottom-up (children before parents). options.__b fires top-down.Some examples of real-world usage: