使用 DHTMLX React Gantt 与 Remix 开发项目规划应用
Remix路由中的DHTMLX React甘特图:具备稳定的配置、data.save回调功能,以及用于项目规划的可选命令式API访问,无需使用SSR变通方案。
来源: Using DHTMLX React Gantt and Remix for Project Planning Apps
在 React 中开发项目规划界面时,通常需要同时应对两种压力:客户端端需实现密集的交互式调度功能,同时数据传输又不能影响图表的正常显示。随着任务图规模的扩大和工作流的复杂化,保持甘特图的响应速度既取决于图表库本身的性能,也取决于数据加载的机制。
Remix 为这种权衡提供了服务器端渲染的解决方案。与 DHTMLX React Gantt 结合使用后,它能够让规划界面高效地加载数据,同时仍允许用户自由拖动时间轴、编辑任务及建立任务关联。GitHub 上的公开示例项目 DHTMLX/react-gantt-remix-starter 展示了这种集成的具体实现方式:https://github.com/DHTMLX/react-gantt-remix-starter
Remix 为 React 甘特图应用带来的优势
早前的相关文章已将复杂的调度组件与 Next.js SSR 结合使用。Remix 从不同的角度切入这一集成方式:它借助常见的 Web API 和 React Router,而非另创一套并行数据获取模型。
这样的选择使得在源代码结构中理解路由与数据流动更为容易。对于甘特图、调度器以及其他数据量较大的控制面板,其交互往往需要明确地与服务器操作关联起来,因此清晰的路由和加载器结构比晦涩的框架机制更有帮助。
该入门指南重点讲解了 Remix 与 React Gantt 之间的渲染流程,涵盖以下内容:
- 从路由加载数据
- 保持甘特图配置的引用稳定性
- 将 UI 修改结果反馈回图表中
- 在属性信息不足时调用甘特图 API
加载器、操作逻辑以及数据持久化功能有意被排除在讨论范围之外,因为这些内容会随着不同产品架构而变化。该演示的目的是展示 DHTMLX React Gantt 可以直接融入 Remix 的渲染模型中,无需依赖仅支持 SSR 的封装层或特殊处理。
从 9.0.12 版本开始,DHTMLX React Gantt 能够与 Next.js、Remix 等 SSR 框架配合使用,无需额外的仅客户端运行的外壳或一次性配置。
集成细节:连接 Remix 与 DHTMLX React Gantt
以下具体的实现要点决定了 Remix 与 React Gantt 能够在真实路由中正常工作。
在 Remix 路由中渲染甘特图
该图表存在于独立的 GanttChart 组件中。在 Remix 中,只需将该组件导入到普通路由中,并像处理其他 React 组件树一样进行渲染即可,无需使用任何特殊的路由 API。
import GanttChart from '~/components/Gantt/Gantt';
import type { Route } from './+types/home';
import { tasks, links } from '~/data/demoData';
export default function Home() {
return (
<div style={{ width: '100vw', height: '100vh' }}>
<GanttChart tasks={tasks} links={links} />
</div>
);
}
该路由负责页面布局和数据流管理,而 React Gantt 负责绘制时间轴及处理编辑操作。任务和链接以属性形式传入,变更则通过 save 回调函数进行保存。
示例使用的是静态演示数据,因此结构一目了然。当 Remix 加载器提供从服务器获取的任务和链接时,相同的属性路径依然适用。
一个容易忽略的问题是:Gantt 容器需要明确的尺寸设置。如果没有指定高度(例如 width: '100vw', height: '100vh'),组件虽能加载,但图表仍会显示为空白。
保持 Gantt 配置的稳定性
GanttConfig 负责控制比例尺、日期、网格宽度以及相关的 UI 设置。
在渲染过程中分配的普通对象会在每次迭代时获得新的引用。将全新的配置对象传入 Gantt 可以强制其完全重新初始化。演示中通过 useMemo 将配置对象固定:
const config: GanttConfig = useMemo(
() => ({
grid_width: 500,
scale_height: 90,
scales: [
{ unit: 'year', step: 1, date: '%Y' },
{ unit: 'month', step: 1, date: '%M' },
{ unit: 'day', step: 1, date: '%d %M' },
],
}),
[]
);
经过记忆化的对象只会创建一次,并在整个组件的生命周期内重复使用,因此父组件的偶尔渲染不会导致图表重新生成。
利用 data.save 处理用户修改
Gantt 不仅是图表,更是编辑工具。用户可以添加任务、调整日期、重新设置依赖关系以及删除行。
DHTMLX React Gantt 通过 data.save 展示这些修改:
data={{
save: (entity: string, action: string, data: Task | Link, id: string | number) => {
console.log(`${entity} - ${action} - ${id}`, data);
},
}}
在示例项目中,该回调仅用于记录日志。而在实际应用中,这里会通过 Remix 操作、HTTP 调用或本地状态更新来持久化这些变更。该回调是连接图表操作与数据层的桥梁;具体处理方式取决于应用程序的架构。
需要时访问 Gantt API
某些场景需要的不仅仅是声明式属性:比如在代码中滚动时间轴、读取任务数据,或添加自定义行为。
演示中通过 useRef 保存了 Gantt 实例:
const ganttRef = useRef<ReactGanttRef>(null);
const gantt = ganttRef.current?.instance;
if (!gantt) return;
// here you can call any Gantt API method
console.log('All tasks:', gantt.getTaskByTime());
gantt.showDate(new Date());
该引用可直接访问底层 API,而无需强制触发 React 的重新渲染。简单的图表可能根本不需要这种方式。但随着产品功能日益复杂,通过命令式方式访问才能实现实用的自定义交互。
明确了这些机制后,就可以更轻松地完整理解入门代码库以及位于 https://docs.dhtmlx.com/gantt/integrations/react/remix/ 的 Remix 集成指南。
总结
Remix 入门示例并非完整的产品架构,它展示了渲染流程、数据传递以及 Gantt 交互如何与功能丰富的调度组件一同存在于一个 Remix 项目中。
从那里你可以添加服务器持久化功能、引入存储机制,或通过自定义逻辑扩展图表功能。结合文档指南,该演示为适合服务器端渲染的项目规划界面提供了可行的基础。