-
-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Improve table devtools performance #6474
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: beta
Are you sure you want to change the base?
Changes from all commits
a439984
e07de2e
18ffccd
b28a1c1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| export { TableDevtoolsPanel } from './TableDevtools' | ||
| export { TableDevtoolsPanel } from './production/TableDevtools' | ||
| export type { TableDevtoolsAngularInit } from './TableDevtools' | ||
| export { tableDevtoolsPlugin } from './plugin' | ||
| export { tableDevtoolsPlugin } from './production/plugin' | ||
| export { injectTanStackTableDevtools } from './injectTanStackTableDevtools' | ||
| export type { InjectTanStackTableDevtoolsOptions } from './injectTanStackTableDevtools' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| import { computed, effect } from '@angular/core' | ||
| import { TableDevtoolsCore } from '@tanstack/table-devtools/production' | ||
| import type { DevtoolsPanelProps } from '@tanstack/devtools-utils/angular' | ||
| import type { TableDevtoolsAngularInit } from '../TableDevtools' | ||
|
|
||
| function resolvePanelProps( | ||
| props?: TableDevtoolsAngularInit, | ||
| ): DevtoolsPanelProps { | ||
| return { | ||
| theme: props?.theme ?? 'dark', | ||
| devtoolsOpen: props?.devtoolsOpen ?? false, | ||
| } | ||
| } | ||
|
|
||
| type TableDevtoolsPanelComponent = () => ( | ||
| inputs: () => TableDevtoolsAngularInit, | ||
| hostElement: HTMLElement, | ||
| ) => () => void | ||
|
|
||
| export const TableDevtoolsPanel: TableDevtoolsPanelComponent = | ||
| () => (props, host) => { | ||
| const panel = host.ownerDocument.createElement('div') | ||
| panel.style.height = '100%' | ||
| host.appendChild(panel) | ||
|
|
||
| const panelProps = computed(() => resolvePanelProps(props()), { | ||
| equal: (previous, next) => | ||
| previous.theme === next.theme && | ||
| previous.devtoolsOpen === next.devtoolsOpen, | ||
| }) | ||
| const panelEffect = effect((onCleanup) => { | ||
| const instance = new TableDevtoolsCore() | ||
| void instance.mount(panel, panelProps()) | ||
| onCleanup(() => instance.unmount()) | ||
| }) | ||
|
|
||
| return () => { | ||
| panelEffect.destroy() | ||
| panel.remove() | ||
| } | ||
| } | ||
|
Comment on lines
+20
to
+41
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "Repository files matching TableDevtools:"
fd -i 'TableDevtools\.(ts|tsx|js|jsx)$' .
echo
echo "Production file outline:"
ast-grep outline packages/angular-table-devtools/src/production/TableDevtools.ts --view compact || true
echo
echo "Dev file outline:"
ast-grep outline packages/angular-table-devtools/src/TableDevtools.ts --view compact || true
echo
echo "Relevant production file:"
cat -n packages/angular-table-devtools/src/production/TableDevtools.ts | sed -n '1,220p'
echo
echo "Relevant dev file:"
cat -n packages/angular-table-devtools/src/TableDevtools.ts | sed -n '1,220p' 2>/dev/null || true
echo
echo "Search for TableDevtoolsCore mount/unmount and panelProps usages:"
rg -n "class TableDevtoolsCore|TableDevtoolsCore|panelProps|effect\\(|resolvePanelProps|inject\\(" packages/angular-table-devtools/src || true
echo
echo "Search for devtools panel definitions:"
rg -n "TableDevtoolsPanel|devtoolsOpen|theme" packages/angular-table-devtools/src -S || trueRepository: TanStack/table Length of output: 8615 Reuse a single
🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| import { createAngularPlugin } from '@tanstack/devtools-utils/angular' | ||
| import { TableDevtoolsPanel } from './TableDevtools' | ||
|
|
||
| type TableDevtoolsPluginFactory = ReturnType<typeof createAngularPlugin>[0] | ||
|
|
||
| const [plugin] = createAngularPlugin({ | ||
| name: 'TanStack Table', | ||
| render: TableDevtoolsPanel, | ||
| }) | ||
|
|
||
| export const tableDevtoolsPlugin: TableDevtoolsPluginFactory = plugin |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| 'use client' | ||
|
|
||
| export { TableDevtoolsPanel } from './PreactTableDevtools' | ||
| export { TableDevtoolsPanel } from './production/PreactTableDevtools' | ||
| export type { TableDevtoolsPreactInit } from './PreactTableDevtools' | ||
| export { tableDevtoolsPlugin } from './plugin' | ||
| export { tableDevtoolsPlugin } from './production/plugin' | ||
| export { useTanStackTableDevtools } from './useTanStackTableDevtools' | ||
| export type { UseTanStackTableDevtoolsOptions } from './useTanStackTableDevtools' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| import { h } from 'preact' | ||
| import { useMemo } from 'preact/hooks' | ||
| import { createPreactPanel } from '@tanstack/devtools-utils/preact' | ||
| import { TableDevtoolsCore } from '@tanstack/table-devtools/production' | ||
| import type { DevtoolsPanelProps } from '@tanstack/devtools-utils/preact' | ||
| import type { JSX } from 'preact' | ||
| import type { TableDevtoolsPreactInit } from '../PreactTableDevtools' | ||
|
|
||
| type TableDevtoolsPanelComponent = ( | ||
| props?: TableDevtoolsPreactInit, | ||
| ) => JSX.Element | ||
|
|
||
| const [TableDevtoolsPanelBase] = createPreactPanel(TableDevtoolsCore) | ||
|
|
||
| function resolvePanelProps( | ||
| props?: TableDevtoolsPreactInit, | ||
| ): DevtoolsPanelProps { | ||
| return { | ||
| theme: props?.theme ?? 'dark', | ||
| devtoolsOpen: props?.devtoolsOpen ?? false, | ||
| } | ||
| } | ||
|
|
||
| export const TableDevtoolsPanel: TableDevtoolsPanelComponent = (props) => { | ||
| const theme = props?.theme | ||
| const devtoolsOpen = props?.devtoolsOpen | ||
| const panelProps = useMemo( | ||
| () => resolvePanelProps({ theme, devtoolsOpen }), | ||
| [devtoolsOpen, theme], | ||
| ) | ||
| return h(TableDevtoolsPanelBase, panelProps) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| import { createPreactPlugin } from '@tanstack/devtools-utils/preact' | ||
| import { TableDevtoolsPanel } from './PreactTableDevtools' | ||
|
|
||
| type PreactTableDevtoolsPlugin = ReturnType< | ||
| ReturnType<typeof createPreactPlugin>[0] | ||
| > | ||
|
|
||
| const [plugin] = createPreactPlugin({ | ||
| name: 'TanStack Table', | ||
| Component: TableDevtoolsPanel, | ||
| }) | ||
|
|
||
| export const tableDevtoolsPlugin: () => PreactTableDevtoolsPlugin = plugin |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| 'use client' | ||
|
|
||
| export { TableDevtoolsPanel } from './ReactTableDevtools' | ||
| export { TableDevtoolsPanel } from './production/ReactTableDevtools' | ||
| export type { TableDevtoolsReactInit } from './ReactTableDevtools' | ||
| export { tableDevtoolsPlugin } from './plugin' | ||
| export { tableDevtoolsPlugin } from './production/plugin' | ||
| export { useTanStackTableDevtools } from './useTanStackTableDevtools' | ||
| export type { UseTanStackTableDevtoolsOptions } from './useTanStackTableDevtools' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| import { createElement, useMemo } from 'react' | ||
| import { createReactPanel } from '@tanstack/devtools-utils/react' | ||
| import { TableDevtoolsCore } from '@tanstack/table-devtools/production' | ||
| import type { DevtoolsPanelProps } from '@tanstack/devtools-utils/react' | ||
| import type { JSX } from 'react' | ||
| import type { TableDevtoolsReactInit } from '../ReactTableDevtools' | ||
|
|
||
| type TableDevtoolsPanelComponent = ( | ||
| props?: TableDevtoolsReactInit, | ||
| ) => JSX.Element | ||
|
|
||
| const [TableDevtoolsPanelBase] = createReactPanel(TableDevtoolsCore) | ||
|
|
||
| function resolvePanelProps(props?: TableDevtoolsReactInit): DevtoolsPanelProps { | ||
| return { | ||
| theme: props?.theme ?? 'dark', | ||
| devtoolsOpen: props?.devtoolsOpen ?? false, | ||
| } | ||
| } | ||
|
|
||
| export const TableDevtoolsPanel: TableDevtoolsPanelComponent = (props) => { | ||
| const theme = props?.theme | ||
| const devtoolsOpen = props?.devtoolsOpen | ||
| const panelProps = useMemo( | ||
| () => resolvePanelProps({ theme, devtoolsOpen }), | ||
| [devtoolsOpen, theme], | ||
| ) | ||
| return createElement(TableDevtoolsPanelBase, panelProps) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| import { createReactPlugin } from '@tanstack/devtools-utils/react' | ||
| import { TableDevtoolsPanel } from './ReactTableDevtools' | ||
|
|
||
| type TableDevtoolsPluginFactory = ReturnType<typeof createReactPlugin>[0] | ||
|
|
||
| const [plugin] = createReactPlugin({ | ||
| name: 'TanStack Table', | ||
| Component: TableDevtoolsPanel, | ||
| }) | ||
|
|
||
| export const tableDevtoolsPlugin: TableDevtoolsPluginFactory = plugin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
Repository: TanStack/table
Length of output: 771
🏁 Script executed:
Repository: TanStack/table
Length of output: 15688
🏁 Script executed:
Repository: TanStack/table
Length of output: 198
🏁 Script executed:
Repository: TanStack/table
Length of output: 32720
🌐 Web query:
@tanstack/devtools-utils 0.6.0 constructCoreClass ClassType mount unmount💡 Result:
In
@tanstack/devtools-utils, theconstructCoreClassfunction is used to create a lazy-loaded "core class" for devtools [1][2]. This utility helps in decoupling the devtools implementation from the main application, allowing the devtools core to be loaded only when needed [1][2]. TheClassTypeexpected by framework-specific panel factories (such ascreateReactPanel,createSolidPanel, etc.) refers to a class with a specific interface [2][3]: 1. mount(el: HTMLElement, theme: 'light' | 'dark'): This method is called by the framework adapter when the panel is mounted into the DOM. It provides the container element (el) and the current devtoolstheme, allowing the devtools to render into that container [3]. 2. unmount: This method is called when the panel is removed from the DOM, allowing for necessary cleanup of the devtools instance [2][3]. By wrapping your devtools core class withconstructCoreClass, you enable efficient lazy-loading, while the framework-specific panel factories (e.g.,createSolidPanel) handle the automated invocation ofmountandunmountwithin the component lifecycle (using hooks likeonMount/onCleanupin Solid oruseEffect/useLayoutEffectlogic in React) [2][3]. Example usage pattern: // 1. Define the core class const [MyDevtoolsCore, NoOpCore] = constructCoreClass( => import('./MyDevtoolsUI'),); // 2. Wrap it for a framework (e.g., Solid) const [MyPanel, NoOpPanel] = createSolidPanel(MyDevtoolsCore); [2]Citations:
🌐 Web query:
@tanstack/devtools-utils 0.6.0 angular DevtoolsPanelProps createAngularPanel💡 Result:
In version 0.6.0 of
@tanstack/devtools-utils, createAngularPanel is a factory function designed to facilitate the creation of Angular devtools panels from class-based devtools cores [1]. It returns a tuple containing the panel component and a no-op variant: const [MyPanel, NoOpPanel] = createAngularPanel(MyDevtoolsCore) [1] The resulting panel component is a standalone Angular component that handles the mounting and unmounting of the provided core class [1]. It uses Angular's afterNextRender to mount the core instance into a div element and cleans up via DestroyRef.onDestroy [1]. The component accepts theme and devtoolsProps as signal inputs [1]. Additionally, the package provides the DevtoolsPanelProps type for Angular, which can be imported from@tanstack/devtools-utils/angular[1]. This interface defines the expected properties, such as theme, for devtools panels [1][2]. For defining plugins in Angular, the package also includes the createAngularPlugin function, which allows wrapping an Angular component class into a plugin definition [1]. This function returns a tuple of [Plugin, NoOpPlugin] and accepts the plugin name and the component class as arguments [1].Citations:
🌐 Web query:
TanStack devtools TableDevtools open close tab selected state devtoolsOpen💡 Result:
TanStack Table Devtools rely on the TanStack Devtools host package to provide the UI, while the framework-specific table adapters (e.g.,
@tanstack/react-table-devtools) provide the integration [1][2]. Regarding your specific interests: Open/Close State The visibility of the devtools panel is managed by the host TanStack Devtools package, typically integrated via a plugin like tableDevtoolsPlugin at the app root [1][2]. In older or specific framework implementations, internal state for visibility (often tracked as isOpen) is managed internally within the devtools component, sometimes persisting to localStorage (e.g., 'reactTableDevtoolsOpen') to maintain state across page refreshes [3]. Tab Selected State The active tab state (such as "Features", "Options", "State", "Rows", or "Columns") is managed internally by the devtools Shell component [4][5]. This state is typically handled via a context provider (e.g., TableDevtoolsContext) within the devtools package, which maintains an activeTab state and exposes an setActiveTab function to switch between views [4][5]. devtoolsOpen If you are looking for a programmatic way to control or reference the open state, note that the official documentation recommends mounting the devtools via the provided plugin system [1][2]. Direct manipulation of internal variables like devtoolsOpen is not the standard API; instead, users are expected to interact with the devtools through the official plugin configuration and registration process using useTanStackTableDevtools [1][2]. To implement the devtools, follow these steps [1][2]: 1. Assign a unique key to each table instance [1]. 2. Mount the TanStackDevtools host with the tableDevtoolsPlugin at the app root [1]. 3. Register your table instance using the framework-specific hook (e.g., useTanStackTableDevtools(table)) [1][2]. For production environments, ensure you import adapters from the /production entrypoint to prevent unnecessary bloat [1][2].Citations:
Avoid rebuilding
TableDevtoolsCoreon every prop change.Angular re-runs this effect whenever
props()changes; the previousonCleanupcallsinstance.unmount(), so eachthemeordevtoolsOpenupdate destroys the mounted instance and creates a new one. TogglingdevtoolsOpentherefore tears down the devtools shell and loses internal UI state. Use a stableTableDevtoolsCoreinstance and update its props instead of remounting after each tracked signal change.🤖 Prompt for AI Agents