在Grid.js中使用SolidJS组件遇内存泄漏错误求助
在Grid.js中使用SolidJS组件作为自定义Formatter的正确姿势
我尝试在Grid.js里用自定义Formatter渲染SolidJS组件,但碰到了这个错误:
computations created outside a
createRootorrenderwill never be disposed
我试过参照Grid.js的React适配器写法来实现,但没成功,想知道这种场景下该怎么正确用SolidJS的渲染系统。
问题代码
import { Component, JSXElement, mergeProps } from 'solid-js'; import { Grid, createRef, h } from 'gridjs'; import 'gridjs/dist/theme/mermaid.css'; import { onMount } from 'solid-js'; import { render } from 'solid-js/web'; type Row = [id: number, name: string, age: number]; type Cells<T extends [...any[]]> = { [K in keyof T]: { data: T[K]; }; }; type FormatterRow<T extends [...any[]]> = { cells: Cells<T>; }; const NameCell: Component<{ id: Row[0]; name: Row[1] }> = (props) => { return <a href={`/user/${props.id}`}>{props.name}</a>; }; const Wrapper: Component<{ element: JSXElement; parent?: string }> = ( rawProps ) => { const props = mergeProps({ parent: 'div' }, rawProps); const ref = createRef(); onMount(() => { render(() => props.element, ref.current); }); return h(props.parent, { ref }); }; const wrap = (element: JSXElement, parent?: string) => { return h(Wrapper, { element, parent }); }; const Table: Component<{ rows: Row[] }> = (props) => { let gridRef!: HTMLDivElement; const grid = new Grid({ columns: [ { name: 'Id', hidden: true }, { name: 'Name', formatter: ( name: Row[1], { cells: [{ data: id }] }: FormatterRow<Row> ) => wrap(<NameCell id={id} name={name} />), }, 'Age', ], data: props.rows, sort: true, search: true, }); onMount(() => { grid.render(gridRef); }); return <div ref={gridRef} />; }; const App: Component = () => { const rows: Row[] = [ [1, 'Andrew', 14], [2, 'Mike', 45], [3, 'Elsa', 28], ]; return <Table rows={rows} />; }; export default App;
解决方案
错误的核心是SolidJS的计算没有被挂载到可销毁的根节点上。Grid.js的自定义Formatter会动态创建、销毁DOM元素,直接用render会导致Solid的根无法被清理,因此需要用createRoot手动管理根的生命周期,同时在Grid.js元素被移除时销毁这个根。
修改后的关键代码
- 重构Wrapper组件,添加根生命周期管理:
import { onCleanup, createRoot } from 'solid-js'; const Wrapper: Component<{ element: JSXElement; parent?: string }> = (rawProps) => { const props = mergeProps({ parent: 'div' }, rawProps); const ref = createRef<HTMLElement>(); let dispose: (() => void) | undefined; onMount(() => { // 创建Solid根并保存销毁函数 dispose = createRoot((dispose) => { render(() => props.element, ref.current!); return dispose; }); }); // 组件卸载时销毁Solid根,清理资源 onCleanup(() => { dispose?.(); }); return h(props.parent, { ref }); };
- 其余代码保持不变即可,Grid.js的
formatter返回的虚拟节点结构已经和Wrapper适配。
原理说明
createRoot会创建独立的Solid渲染根,返回的dispose函数可以手动销毁该根下的所有计算和组件实例。onCleanup在Wrapper组件被卸载时触发,调用dispose就能彻底清理Solid相关资源,避免内存泄漏和错误提示。- 相比直接使用
render,createRoot让我们能完全控制根的生命周期,完美适配Grid.js动态操作DOM的场景。
内容的提问来源于stack exchange,提问作者Meowster
相关产品推荐
相关产品推荐

