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

Syncfusion Dashboard Layout如何使用带props的React组件作为面板

Syncfusion Dashboard Layout 嵌入响应式React组件解决方案

Syncfusion Dashboard Layout 组件默认的content配置项仅支持传入静态字符串、原生HTML节点,内部不会走React虚拟DOM渲染流程,因此直接传入React组件时无法触发props更新、重渲染等响应式逻辑,可通过以下两种方案实现动态交互渲染:

  • 方案1:利用面板渲染回调手动挂载React组件

    组件渲染完成后会触发created事件,可在事件回调中获取每个面板的内容容器DOM节点,通过React官方提供的挂载方法将自定义组件渲染到对应容器中,组件的状态、props更新完全遵循React原生逻辑。
    示例代码:

    import { useEffect, useRef, useState } from 'react';
    import { createRoot } from 'react-dom/client';
    import { DashboardLayoutComponent, PanelsDirective, PanelDirective } from '@syncfusion/ej2-react-layouts';
    import CustomDynamicWidget from './CustomDynamicWidget';
    
    export default function CustomDashboard() {
      const dashboardIns = useRef(null);
      const panelRootMap = useRef(new Map());
      const [widgetProps, setWidgetProps] = useState({ count: 0 });
    
      const renderPanelContent = () => {
        const contentContainers = dashboardIns.current.element.querySelectorAll('.e-panel-content');
        contentContainers.forEach((container, idx) => {
          if (panelRootMap.current.has(container)) return;
          const root = createRoot(container);
          root.render(<CustomDynamicWidget {...widgetProps} />);
          panelRootMap.current.set(container, root);
        });
      };
    
      // props变化时手动更新已挂载的组件
      useEffect(() => {
        panelRootMap.current.forEach((root) => {
          root.render(<CustomDynamicWidget {...widgetProps} />);
        });
      }, [widgetProps]);
    
      // 组件卸载时清理挂载实例,避免内存泄漏
      useEffect(() => {
        return () => {
          panelRootMap.current.forEach(root => root.unmount());
          panelRootMap.current.clear();
        };
      }, []);
    
      return (
        <div>
          <button onClick={() => setWidgetProps(prev => ({count: prev.count + 1}))}>
            触发组件更新
          </button>
          <DashboardLayoutComponent
            ref={dashboardIns}
            created={renderPanelContent}
            cellSpacing={[10, 10]}
            columns={4}
          >
            <PanelsDirective>
              <PanelDirective sizeX={2} sizeY={2} row={0} col={0} content="" />
              <PanelDirective sizeX={2} sizeY={2} row={0} col={2} content="" />
            </PanelsDirective>
          </DashboardLayoutComponent>
        </div>
      );
    }
    
  • 方案2:使用React Portal渲染面板内容

    如果希望完全遵循React的组件树逻辑、共享上层Context,可以在拿到面板内容容器DOM后,通过ReactDOM.createPortal将自定义组件渲染到对应容器中。这种写法不需要手动管理React根实例,组件的更新、卸载逻辑会由React自动处理,代码更贴合常规React开发模式。
    注意如果面板拖拽、尺寸调整后容器DOM被重建,需要更新Portal的目标容器节点,避免渲染位置异常。

注意事项

  • 不要直接将React JSX元素传入面板的content属性,组件内部会直接将值作为原生DOM插入,不会解析React的虚拟DOM结构,无法绑定响应式更新逻辑
  • 如果开启了面板拖拽、动态增删面板功能,需要在面板变更事件触发后重新检查容器DOM,补做组件挂载逻辑
  • 动态移除面板时需要同步卸载对应容器上挂载的React组件,避免内存泄漏

内容的提问来源于stack exchange,提问作者Ognjen Popovic

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 16:34:47