用途
本技能介绍如何使用 @tanstack/devtools-utils 的工厂函数,为不同前端框架创建 devtools 插件适配器。每个框架都有对应的子路径导出(/react、/vue、/solid、/preact),每个子路径提供两类工厂函数,用于把自定义组件或基于类的 devtools 核心接入 TanStack Devtools。
主要能力
插件工厂
每个 createXPlugin 返回 readonly [Plugin, NoOpPlugin] 元组:
- Plugin:返回带元数据的插件对象,其 render 函数渲染你的组件。
- NoOpPlugin:返回相同元数据但渲染空片段的插件对象。
面板工厂
每个 createXPanel 返回 readonly [Panel, NoOpPanel] 元组:
- Panel:框架组件,创建 <div style="height:100%">,实例化核心类,在挂载时调用 core.mount(el, theme),在清理时调用 core.unmount()。
- NoOpPanel:渲染空片段。
DevtoolsPanelProps
React、Solid、Preact:
interface DevtoolsPanelProps {
theme?: 'light' | 'dark'
}
Vue(注意包含 'system'):
interface DevtoolsPanelProps {
theme?: 'dark' | 'light' | 'system'
}
从框架子路径导入类型:
import type { DevtoolsPanelProps } from '@tanstack/devtools-utils/react'
import type { DevtoolsPanelProps } from '@tanstack/devtools-utils/vue'
import type { DevtoolsPanelProps } from '@tanstack/devtools-utils/solid'
import type { DevtoolsPanelProps } from '@tanstack/devtools-utils/preact'
使用方式
React 示例
import { createReactPlugin } from '@tanstack/devtools-utils/react'
function MyStorePanel({ theme }: { theme?: 'light' | 'dark' }) {
return <div className={theme}>My Store Devtools</div>
}
const [MyPlugin, NoOpPlugin] = createReactPlugin({
name: 'My Store',
id: 'my-store',
defaultOpen: false,
Component: MyStorePanel,
})
// Tree-shaking: use NoOp in production
const ActivePlugin =
process.env.NODE_ENV === 'development' ? MyPlugin : NoOpPlugin
配合基于类的面板
import {
createReactPanel,
createReactPlugin,
} from '@tanstack/devtools-utils/react'
class MyDevtoolsCore {
mount(el: HTMLElement, theme: 'light' | 'dark') {
/* render into el */
}
unmount() {
/* cleanup */
}
}
const [MyPanel, NoOpPanel] = createReactPanel(MyDevtoolsCore)
const [MyPlugin, NoOpPlugin] = createReactPlugin({
name: 'My Store',
Component: MyPanel,
})
各框架 API 差异
React 与 Preact 使用选项对象:
createReactPlugin({ name, id?, defaultOpen?, Component }) // => [Plugin, NoOpPlugin]
createPreactPlugin({ name, id?, defaultOpen?, Component }) // => [Plugin, NoOpPlugin]
Component 接收 DevtoolsPanelProps(含 theme)。Plugin() 返回 { name, id?, defaultOpen?, render(el, theme) }。Preact 与 React 相同,但使用 Preact JSX 类型和 preact/hooks。
Vue 使用位置参数,而非选项对象:
createVuePlugin(name: string, component: DefineComponent) // => [Plugin, NoOpPlugin]
以 (name, component) 作为独立参数传入。Plugin(props) 返回 { name, component, props },透传 props。NoOpPlugin(props) 返回 { name, component: Fragment, props }。Vue 的 DevtoolsPanelProps.theme 还接受 'system'。
Solid 与 React 的 API 相同,但内部实现不同:
createSolidPlugin({ name, id?, defaultOpen?, Component }) // => [Plugin, NoOpPlugin]
Component 必须是 Solid 组件函数 (props: DevtoolsPanelProps) => JSX.Element。render 函数内部返回 <Component theme={theme} />,由 Solid 处理响应式。Solid 还从 @tanstack/devtools-utils/solid/class 导出 constructCoreClass,用于构建懒加载的 devtools 核心。
常见错误
在 Vue 适配器中使用 React JSX 模式(严重)
Vue 使用位置参数 (name, component),不是选项对象。
// WRONG -- will fail at compile time or produce garbage at runtime
const [MyPlugin, NoOpPlugin] = createVuePlugin({
name: 'My Plugin',
Component: MyPanel,
})
// CORRECT
const [MyPlugin, NoOpPlugin] = createVuePlugin('My Plugin', MyPanel)
Vue 插件在调用时也不同,需要传入 props:
// WRONG -- calling Plugin() with no args (React pattern)
const plugin = MyPlugin()
// CORRECT -- Vue Plugin takes props
const plugin = MyPlugin({ theme: 'dark' })
Solid 渲染 prop 未包装为函数(严重)
使用 Solid 组件时,Component 必须是函数引用,而非原始 JSX。
// WRONG -- evaluates immediately, breaks Solid reactivity
createSolidPlugin({
name: 'My Store',
Component: <MyPanel />, // This is JSX.Element, not a component function
})
// CORRECT -- pass the component function itself
createSolidPlugin({
name: 'My Store',
Component: (props) => <MyPanel theme={props.theme} />,
})
// ALSO CORRECT -- pass the component reference directly
createSolidPlugin({
name: 'My Store',
Component: MyPanel,
})
忽略生产环境的 NoOp 变体(高)
工厂返回 [Plugin, NoOpPlugin],两者都必须解构使用才能正确 tree-shaking。
// WRONG -- NoOp variant discarded, devtools code ships to production
const [MyPlugin] = createReactPlugin({ name: 'Store', Component: MyPanel })
// CORRECT -- conditionally use NoOp in production
const [MyPlugin, NoOpPlugin] = createReactPlugin({
name: 'Store',
Component: MyPanel,
})
const ActivePlugin =
process.env.NODE_ENV === 'development' ? MyPlugin : NoOpPlugin
未向面板组件传递 theme prop(中)
DevtoolsPanelProps 包含 theme。devtools 外壳会传入它,以便面板匹配明暗模式。若组件忽略它,面板将无法适应主题变化。
// WRONG -- theme is ignored
const Component = () => <div>My Panel</div>
// CORRECT -- use theme for styling
const Component = ({ theme }: DevtoolsPanelProps) => (
<div className={theme === 'dark' ? 'dark-mode' : 'light-mode'}>My Panel</div>
)
设计张力
核心架构与框架无关,但每个框架有不同习惯:
- React/Preact 使用选项对象,Component 为 JSX 函数组件。
- Vue 使用位置参数,传入 DefineComponent 并透传 props。
- Solid 使用与 React 相同的选项 API,但采用 Solid 的 JSX 与响应式模型。
基于 React 模式训练的智能体容易把 Vue 写错。始终检查导入路径以确定使用哪个工厂 API。
适用场景
适用于需要为 TanStack Devtools 编写自定义插件或面板,并希望同时支持多个前端框架的开发者。通过工厂函数可以复用同一套 devtools 核心逻辑,并为每个框架生成对应的适配器,同时利用 NoOp 变体在生产构建中剔除 devtools 代码。
限制
资料未提供具体的安装命令、版本要求、收费或价格信息。各框架的完整 API 细节可参考 references/react.md、references/vue.md、references/solid.md、references/preact.md。