Using DHTMLX Gantt Chart for React with Redux Toolkit: Principles, Benefits, and Implementation Tips

Modern React apps for project management are often implemented with the use of advanced UI components, providing numerous interaction options. But the use of such functional tools is often associated with the tricky task of keeping the UI in sync with a range of user actions and data updates. A vivid example of this challenge is a Gantt chart, where dragging a task, updating dependencies, or adjusting the timeline can affect various parts of the application state. In such scenarios, the proper state management becomes essential for a good user experience.

In this blog post, you will learn why the combination of DHTMLX Gantt for React with Redux Toolkit works well for building data-driven Gantt apps, as well as practical tips on how to make it work in your project.

How DHTMLX Gantt for React Aligns with Redux Toolkit Data Flow

Our React Gantt component offers a wide range of interaction features, from multiple data-level operations (CRUD) and global settings (zoom, filtering, theme switching, etc.) to advanced scheduling options (auto-scheduling, critical path, resource allocation). During the DHTMLX Gantt React integration in your app, you can access all these and many other features via the API of our mature JS Gantt.

Commonly, Gantt charts include numerous interrelated tasks, and a single user action can trigger a whole series of changes in the project workflow. It brings up the question of how to handle these changes accurately and predictably. The answer is to empower the Gantt with an effective state management solution like Redux Toolkit.
DHTMLX Gantt for React meets two core criteria for smooth integration with Redux Toolkit. They are the following:

  • Declarative approach to data handling

Our component adheres to React’s declarative data flows i.e., arrays of Gantt data (tasks, links, resources) as well as configuration settings (themes, columns, templates) are passed as React props. In the context of Redux integration, it means that the Gantt component can accept external data via props from a store of the state library. Any changes to these props trigger an automatic update of the Gantt chart.

  • Callback mechanism for user actions

Now that we know how updates are applied, it remains to figure out how an external state manager like Redux becomes aware of data changes. The component exposes the details about user interactions through callback functions. This mechanism means that Redux acts as the source of truth. The use of callback functions allows delegating the actual state update to a centralized store instead of handling changes internally.

Since Redux Toolkit is written in TypeScript, it is also worth noting that our Gantt component offers full TypeScript support. It is not a critical requirement, but it still facilitates the integration process by ensuring type safety across the entire data flow.

Now, let us find out what makes Redux Toolkit a good choice for a Gantt-based React project.

How Redux Toolkit Can Benefit React Gantt Project

The standard Redux library is often criticized for excessive boilerplate code, complex configuration, and the need for multiple external libraries. Redux Toolkit is a more developer-friendly solution that addresses these pain points, becoming a valid choice for components like the Gantt chart for React.

How Does it Work in Practice?

Redux provides a single, centralized store for all Gantt data and settings, organized into feature-specific units called slices. When a user modifies the Gantt chart (e.g., adds a new task), the UI uses a callback function to dispatch an action that describes “what happened” in the chart. After that, the store runs the reducer function that defines how the Gantt state should change in response. Finally, the updated state is passed back to Gantt via props, and the interface rerenders accordingly.

For more details on the Redux data flow, refer to the Redux Toolkit documentation.

Now, we can summarize the main benefits of integrating DHTMLX Gantt for React with Redux Toolkit:

  • Centralized state management. All Gantt data and settings are placed in a single Redux store, ensuring that each part of the UI works with the same source of truth. It helps avoid inconsistencies in data updates across the app.
  • Predictable data flow. A single, unidirectional data flow pattern is used for processing interactions with the Gantt chart. Thus, state transitions become more explicit and easier to follow. This, in turn, contributes to higher debugging efficiency. When something goes wrong after multiple interactions with the same data, Redux Toolkit helps identify the root of such issue without delay.
  • Clear separation of concerns. Redux Toolkit focuses on handling the logic behind user interactions, while the UI component is used to render and capture user input. This keeps responsibilities clearly defined and prevents mixing visual code with business rules.
  • Scalability and maintainability. Redux Toolkit allows the application state to be organized into slices, each describing a specific part of the Gantt chart data and behavior. This modular approach enables easier extension of the Gantt app with new functional capabilities, while maintaining a well-organized and manageable codebase as the project evolves.

Understanding why DHTMLX Gantt for React works well with Redux Toolkit is only the halfway point. Let us move forward and see how this promising Redux Gantt integration is applied in practice.

Highlighting Key Integration Steps of DHTMLX React Gantt with Redux Toolkit

You are already familiar with the main concepts of this integration, such as callbacks, slices, actions, and reducers. Now, it is time to figure out how these pieces come together under the hood for delivering stable state management for the Gantt chart. To be more specific, we’ll consider the implementation of the key elements of the Redux infrastructure (store+slice) and how Redux handles Gantt state changes coming from different sources.

Setting Up Redux State Layer

We want to start with two key concepts on the Redux side that form the foundation for implementing the state management functionality in Gantt projects built with DHTMLX. We are talking about the Redux store and Gantt slices. The store will serve as a single source of truth for Gantt data, while slices encapsulate all the logic required to manage Gantt data with Redux into units.

Configuring Redux Store for Gantt Data

First of all, we need to create a centralized store and attach the Gantt slice reducer, which will interact with Gantt data. A standard Redux store setup typically requires multiple pieces of configuration, but Redux Toolkit offers a simplified way to do that with the configureStore function:

import { configureStore } from '@reduxjs/toolkit';
import ganttReducer from './ganttSlice';

export const store = configureStore({
 reducer: {
   gantt: ganttReducer,
 },
});

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;

The RootState and AppDispatch types are derived from the store instance. These types will be used in conjunction with the useSelector and useDispatch hooks, ensuring type safety when accessing Gantt data and dispatching actions from the UI.

Creating Redux (Gantt) Slice

Now, we specify how the Gantt dataset is stored and updated by implementing the slice logic. In our case, the dataset contains tasks, links, configuration settings such as Zoom, and undo/redo functionality. The Redux slice is created with the createSlice function, which takes the slice name, initial state, and a reducers object containing reducer functions. The createSlice function will automatically generate corresponding action creators for each specified reducer.

const ganttSlice = createSlice({
  name: 'gantt',
  initialState,
  reducers: {
    undo(state) {
        ...
    },
    redo(state) {
      ...
    },
    updateTask(state, action: PayloadAction<SerializedTask>) {
      ...
    },
    createTask(state, action: PayloadAction<SerializedTask>) {
      ...
    },
    deleteTask(state, action: PayloadAction<string>) {
      ...
    },
    updateLink(state, action: PayloadAction<Link>) {
      ...
    },
    createLink(state, action: PayloadAction<Link>) {
      ...
    },
    deleteLink(state, action: PayloadAction<string>) {
      ...
    },
    setZoom(state, action: PayloadAction<ZoomLevel>) {
      ...
    },
  },
});

The complete Gantt slice code is available in the complete DHTMLX Gantt tutorial provided in the documentation.

Key points:

  • The initialState presents the complete Gantt structure stored in Redux, serving as the starting point for all state changes.
  • Each reducer defines how the state changes in response to a specific action (task edits, link updates, zoom changes, and history navigation).
  • Action creators generated by createSlice are dispatched by the UI (or toolbar callbacks, which will be discussed later).
  • The undo/redo feature is implemented with a simple snapshot history for state rollback.

At this point, you should have a clear idea of how to create the Redux store, aggregating the Gantt state, and complement it with the Gantt slice that defines the state structure and update logic.

Scenarios for Managing Gantt State with Redux

We can proceed to the most interesting part of the story, namely, exploring how effective Redux Toolkit is in handling Gantt state with internal and external changes. Internal changes originate from the Gantt component itself, while auxiliary UI elements trigger external changes. Redux Toolkit provides a reliable mechanism, including callbacks and props, for processing both types of updates following the same, easy-to-trace cycle.

Managing Internal Gantt Changes

When a user modifies any task or dependency in the Gantt chart, it is necessary to inform the state manager about the nature of this change. It is done with the help of the data.save callback:

const data: ReactGanttProps['data'] = useMemo(
 () => ({
   save: (entity, action, payload, id) => {
     if (entity === 'task') {
       const task = payload as SerializedTask;
       if (action === 'update') {
         dispatch(updateTask(task));
       } else if (action === 'create') {
         dispatch(createTask(task));
       } else if (action === 'delete') {
         dispatch(deleteTask(String(id)));
       }
     } else if (entity === 'link') {
     ... //similar logic for links
     }
   },
 }),
 [dispatch]
);

The data.save passes contextual information about the update, including:

  • entity – type of the affected entity (task or link)
  • action – action applied to it (create, update, delete)
  • payload – data being changed
  • id – unique identifier of the modified element

Taking into account the entity and action parameters, the callback dispatches the corresponding Redux action. This creates a seamless way to connect Gantt to the Redux store, linking the chart’s internal state changes with centralized Redux updates.

For a deeper understanding of the data.save callback and how it works, check this section in our documentation.

The Gantt component receives updates on the state of specific chart elements (tasks, dependencies, configuration) via store state. Changes are extracted from the Redux store via the useSelector hook:

const { tasks, links, config } = useSelector((state: RootState) => state.gantt);

When the Redux state changes, the data is automatically updated, keeping the chart in sync.

As a result, the data flow in the React Gantt setup follows a predictable cycle:

Gantt UIRedux actionRedux reducerstore updateGantt (tracking store state)UI rerendering.

Controlling Gantt via an External Toolbar

The thing that makes the integration with Redux Toolkit particularly valuable is the possibility of using an external UI element to control the Gantt chart through the Redux store. This approach opens up opportunities for a more flexible control over the Gantt state in comprehensive React project management UIs, while preserving a predictable one-way data flow. Let us briefly explain how it works with DHTMLX Gantt for React using a separate custom toolbar component with undo/redo and zoom controls.

It receives the current zoom level via props and exposes callback functions for undo, redo, and zoom actions:

export interface ToolbarProps {  
  onUndo?: () => void;  
  onRedo?: () => void;  
  onZoom?: (level: ZoomLevel) => void;  
  currentZoom?: ZoomLevel;  
}

When a user clicks a button, the toolbar calls a corresponding callback passed via props, signalling the component about the action:

<Button onClick={() => onUndo?.()}>
  <UndoIcon />
</Button>
     
<Button onClick={() => onRedo?.()}>
  <RedoIcon />
</Button>  
//Other buttons

After that, these callbacks are connected (or dispatched) to Redux actions:

const handleUndo = useCallback(() => {  
  dispatch(undo());  
}, [dispatch]);

const handleRedo = useCallback(() => {  
  dispatch(redo());  
}, [dispatch]);

const handleZoomIn = useCallback(  
  (newZoom: ZoomLevel) => {  
    dispatch(setZoom(newZoom));  
  },  
  [dispatch]  
);

To avoid unnecessary rerendering, we memoize Redux dispatch handlers with useCallback. Then, Redux updates the Gantt slice in the store. Here is the link to the full Toolbar code.

And finally, we render the complete Gantt component:

return (  
  <div style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>  
    <Toolbar onUndo={handleUndo} onRedo={handleRedo} onZoom={handleZoomIn} currentZoom={config.zoom.current} />

    <ReactGantt tasks={tasks} links={links} config={ganttConfig} templates={templates} data={data} ref={ganttRef} />  
  </div>  
);

As you can see, Redux Toolkit maintains the process of Gantt state control within the same predictable data flow, ensuring changes are triggered by interactions within the Gantt chart or via the custom toolbar.

If you need a complete guide on integrating DHTMLX Gantt for React with Redux Toolkit, check out the official tutorial in our documentation. DHTMLX Gantt examples on GitHub also include a corresponding working demo project.

Conclusion

Integrating DHTMLX Gantt for React with Redux Toolkit provides a straightforward state management model for complex project data. No matter whether the Gantt chart is modified internally or via the custom toolbar, Redux accurately processes all changes and ensures that they are promptly reflected in the UI. This approach helps teams build complex React Redux project management apps without tightly coupling UI components to business logic.

Advance your web development with DHTMLX

Gantt chart
Event calendar
Diagram library
30+ other JS components