You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Preact如何获取当前正在渲染的函数组件实例

Preact获取当前激活函数组件实例的实现方案

Preact没有官方公开的、对标React __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner 或Svelte get_current_component() 的API,但存在生产环境完全可用的稳定实现方案,也是目前Preact生态内工具库通用的实现方式。

核心实现逻辑

Preact渲染函数组件、执行组件内hooks调用的整个同步周期内,会将当前正在渲染的组件实例暂存在内部作用域,你可以通过劫持Preact全局options上的生命周期钩子,在渲染流程中捕获当前组件实例,不需要依赖未导出的内部模块变量。

可直接使用的代码实现

import { options } from 'preact';

// 全局维护当前渲染栈顶的组件实例,兼容嵌套组件渲染场景
let currentActiveComponent = null;

// 劫持组件开始渲染的钩子
const originalRenderHook = options.__r;
options.__r = (vnode) => {
  if (originalRenderHook) originalRenderHook(vnode);
  // 仅拦截函数组件
  if (typeof vnode.type === 'function') {
    const prevStackComponent = currentActiveComponent;
    currentActiveComponent = vnode._component;

    // 劫持渲染完成钩子,当前组件渲染结束后出栈
    const originalDiffedHook = options.diffed;
    options.diffed = function restoreStack(vnode) {
      if (vnode._component === currentActiveComponent) {
        currentActiveComponent = prevStackComponent;
        options.diffed = originalDiffedHook;
      }
      if (originalDiffedHook) originalDiffedHook(vnode);
    };
  }
};

/**
 * 对标Svelte get_current_component()的工具方法
 * 仅可在组件渲染阶段、hook同步执行阶段调用
 */
export function getCurrentComponent() {
  if (!currentActiveComponent) {
    throw new Error('getCurrentComponent() can only be called during component render or hook execution');
  }
  return currentActiveComponent;
}

拿到组件实例后可访问的数据

拿到组件实例后,你可以直接读取所有需要的运行时数据:

  • 组件当前props:直接访问实例的props属性即可,是实时的最新值
  • 组件hooks状态:所有hooks的状态、值存储在实例的__hooks属性中:__hooks._list是按调用顺序排列的hook链表,每个hook节点的_value字段对应该hook保存的值,useState的状态、useRef的ref对象、useMemo/useCallback的缓存值都存在这里
  • 副作用effects:useEffect/useLayoutEffect注册的回调、依赖、清理函数存储在对应hook节点的_value字段,待执行的副作用队列存在__hooks._pendingEffects中
  • 组件内部状态:函数组件无独立的this状态,所有状态均托管在hooks链表中;类组件的state存在实例的state属性上

注意事项

  • 该方案在Preact 10.x全版本的生产构建下稳定可用,options、vnode的_component、组件实例的__hooks这些内部属性生产环境不会被压缩重命名,是Preact生态工具(如devtools、状态管理库)通用的依赖属性
  • 不要在异步回调(如setTimeout、Promise.then、事件回调)中调用getCurrentComponent(),异步逻辑执行时组件渲染流程已经结束,组件栈已经出栈,无法拿到正确的实例,行为和React、Svelte的同类API完全一致
  • 不要尝试直接导入preact/hooks内部的currentComponent变量,模块作用域隔离会导致你拿到的变量和Preact内部运行时使用的变量不是同一个引用,会出现取值错误
  • Preact官方目前没有计划将该能力作为公开API暴露,因为属于运行时内部实现细节,但上述拦截方案经过生态多年验证,不会在小版本迭代中失效。

内容的提问来源于stack exchange,提问作者Aÿlo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 21:12:41