Hierarchical Tree Layout in React Diagram
21 Aug 202620 minutes to read
The hierarchical tree layout arranges nodes in a clear parent-child structure. It is suitable for organizational charts, directory structures, and similar hierarchies. The relationship between nodes is defined through connectors or data source fields such as parentId, so an explicit root node is not required.
Hierarchical Tree Layout Output:

Hierarchical Tree Layout with Nodes and Connectors
To arrange nodes in a hierarchical structure, specify the layout type as HierarchicalTree. This approach provides full control over node and connector definitions while leveraging automatic positioning.
NOTE
Before proceeding, ensure that the
@syncfusion/ej2-react-diagramspackage is installed and that theDiagramComponent,Inject(from@syncfusion/ej2-react-diagrams), and the required layout modules are imported in your project.
NOTE
The HierarchicalTree module must be injected into the diagram using the
Injectcomponent, for example:<Inject services={[HierarchicalTree]} />. Without this injection, the hierarchical tree layout will not be applied.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, DataBinding, HierarchicalTree } from "@syncfusion/ej2-react-diagrams";
//Uses layout to auto-arrange nodes on the diagram page
let layout = {
//Sets layout type
type: 'HierarchicalTree'
};
//Initialize nodes for diagram
let nodes = [
{
id: 'Steve-Ceo',
},
{
id: 'Kevin-Manager',
},
{
id: 'Peter-Manager',
},
{
id: 'John-Manager',
},
{
id: 'Mary-CSE',
},
{
id: 'Jim-CSE',
},
{
id: 'Martin-CSE',
},
];
//Initialize connectors for diagram
let connectors = [
{
id: 'Steve-Ceo_Kevin-Manager',
sourceID: 'Steve-Ceo',
targetID: 'Kevin-Manager',
},
{
id: 'Steve-Ceo_Peter-Manager',
sourceID: 'Steve-Ceo',
targetID: 'Peter-Manager',
},
{
id: 'Peter-Manager_John-Manager',
sourceID: 'Peter-Manager',
targetID: 'John-Manager',
},
{
id: 'Peter-Manager_Mary-CSE',
sourceID: 'Peter-Manager',
targetID: 'Mary-CSE',
},
{
id: 'Kevin-Manager_Jim-CSE',
sourceID: 'Kevin-Manager',
targetID: 'Jim-CSE',
},
{
id: 'Kevin-Manager_Martin-CSE',
sourceID: 'Kevin-Manager',
targetID: 'Martin-CSE',
},
];
export default function App() {
return (
<div>
<DiagramComponent
id="container"
width={"100%"}
height={"550px"}
nodes={nodes}
connectors={connectors}
//Uses layout to auto-arrange nodes on the diagram page
layout={layout}
//Sets the default properties for nodes
getNodeDefaults={(node) => {
node.annotations = [{ content: node.id }];
node.width = 100; node.height = 40;
return node;
}}
//Sets the default properties for connectors
getConnectorDefaults={(connector) => {
connector.type = 'Orthogonal';
return connector;
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[DataBinding, HierarchicalTree]} />
</DiagramComponent>
</div>
);
}
// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById("diagram"));
root.render(<App />);import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, ConnectorModel, DataBinding,
NodeModel, HierarchicalTree, LayoutModel } from "@syncfusion/ej2-react-diagrams";
//Uses layout to auto-arrange nodes on the diagram page
let layout: LayoutModel = {
//Sets layout type
type: 'HierarchicalTree'
};
//Initialize nodes for diagram
let nodes: NodeModel[] = [
{
id: 'Steve-Ceo',
},
{
id: 'Kevin-Manager',
},
{
id: 'Peter-Manager',
},
{
id: 'John-Manager',
},
{
id: 'Mary-CSE',
},
{
id: 'Jim-CSE',
},
{
id: 'Martin-CSE',
},
];
//Initialize connectors for diagram
let connectors: ConnectorModel[] = [
{
id: 'Steve-Ceo_Kevin-Manager',
sourceID: 'Steve-Ceo',
targetID: 'Kevin-Manager',
},
{
id: 'Steve-Ceo_Peter-Manager',
sourceID: 'Steve-Ceo',
targetID: 'Peter-Manager',
},
{
id: 'Peter-Manager_John-Manager',
sourceID: 'Peter-Manager',
targetID: 'John-Manager',
},
{
id: 'Peter-Manager_Mary-CSE',
sourceID: 'Peter-Manager',
targetID: 'Mary-CSE',
},
{
id: 'Kevin-Manager_Jim-CSE',
sourceID: 'Kevin-Manager',
targetID: 'Jim-CSE',
},
{
id: 'Kevin-Manager_Martin-CSE',
sourceID: 'Kevin-Manager',
targetID: 'Martin-CSE',
},
];
export default function App() {
return (
<div>
<DiagramComponent
id="container"
width={"100%"}
height={"550px"}
nodes={nodes}
connectors={connectors}
//Uses layout to auto-arrange nodes on the diagram page
layout={layout}
//Sets the default properties for nodes
getNodeDefaults={(node: NodeModel) => {
node.annotations = [{ content: node.id }];
node.width = 100; node.height = 40;
return node;
}}
//Sets the default properties for connectors
getConnectorDefaults={(connector: ConnectorModel) => {
connector.type = 'Orthogonal';
return connector;
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[DataBinding, HierarchicalTree]} />
</DiagramComponent>
</div>
);
}
// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById("diagram") as HTMLElement);
root.render(<App />);Hierarchical Layout with DataSource
For data-driven scenarios, hierarchical layout can be created using a DataSource, which automatically generates nodes and connectors based on the data relationships. This approach reduces the need to define each node and connector manually, making it well suited for larger datasets that may change over time.
NOTE
When using a DataSource, configure
dataSourceSettingswith theidandparentIdfields so the layout can resolve parent-child relationships. Without these fields, the generated nodes cannot be linked into a hierarchical structure.
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, DataBinding, HierarchicalTree } from "@syncfusion/ej2-react-diagrams";
import { DataManager, Query } from "@syncfusion/ej2-data";
//Uses layout to auto-arrange nodes on the diagram page
let layout = {
//Sets layout type
type: 'HierarchicalTree'
};
//Initializes data source
let data = [
{ Name: "Steve-Ceo" },
{ Name: "Kevin-Manager", ReportingPerson: "Steve-Ceo" },
{ Name: "Peter-Manager", ReportingPerson: "Steve-Ceo" },
{ Name: "John- Manager", ReportingPerson: "Peter-Manager" },
{ Name: "Mary-CSE ", ReportingPerson: "Peter-Manager" },
{ Name: "Jim-CSE ", ReportingPerson: "Kevin-Manager" },
{ Name: "Martin-CSE", ReportingPerson: "Kevin-Manager" }
];
let items = new DataManager(data, new Query().take(7));
//Configures data source for diagram
let dataSourceSettings = {
id: 'Name',
parentId: 'ReportingPerson',
dataSource: items
};
export default function App() {
return (
<div>
<DiagramComponent
id="container"
width={"100%"}
height={"550px"}
//Uses layout to auto-arrange nodes on the diagram page
layout={layout}
//Configures data source for diagram
dataSourceSettings={dataSourceSettings}
//Sets the default properties for nodes
getNodeDefaults={(node) => {
node.annotations = [{ content: node.data.Name }];
node.width = 100; node.height = 40;
return node;
}}
//Sets the default properties for connectors
getConnectorDefaults={(connector) => {
connector.type = 'Orthogonal';
return connector;
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[DataBinding, HierarchicalTree]} />
</DiagramComponent>
</div>
);
}
// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById("diagram"));
root.render(<App />);import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, ConnectorModel, DataBinding, NodeModel, HierarchicalTree, LayoutModel, DataSourceModel } from "@syncfusion/ej2-react-diagrams";
import { DataManager, Query } from "@syncfusion/ej2-data";
//Initializes data source
let data: object[] = [
{ Name: "Steve-Ceo" },
{ Name: "Kevin-Manager", ReportingPerson: "Steve-Ceo" },
{ Name: "Peter-Manager", ReportingPerson: "Steve-Ceo" },
{ Name: "John- Manager", ReportingPerson: "Peter-Manager" },
{ Name: "Mary-CSE ", ReportingPerson: "Peter-Manager" },
{ Name: "Jim-CSE ", ReportingPerson: "Kevin-Manager" },
{ Name: "Martin-CSE", ReportingPerson: "Kevin-Manager" }
];
let items: DataManager = new DataManager(data as JSON[], new Query().take(7));
//Uses layout to auto-arrange nodes on the diagram page
let layout: LayoutModel = {
//Sets layout type
type: 'HierarchicalTree'
};
//Configures data source for diagram
let dataSourceSettings: DataSourceModel = {
id: 'Name',
parentId: 'ReportingPerson',
dataSource: items
};
export default function App() {
return (
<div>
<DiagramComponent
id="container"
width={"100%"}
height={"550px"}
//Uses layout to auto-arrange nodes on the diagram page
layout={layout}
//Configures data source for diagram
dataSourceSettings={dataSourceSettings}
//Sets the default properties for nodes
getNodeDefaults={(node: NodeModel) => {
node.annotations = [{ content: (node.data as { Name: 'string' }).Name }];
node.width = 100; node.height = 40;
return node;
}}
//Sets the default properties for connectors
getConnectorDefaults={(connector: ConnectorModel) => {
connector.type = 'Orthogonal';
return connector;
}}
>
{/* Inject necessary services for the diagram */}
<Inject services={[DataBinding, HierarchicalTree]} />
</DiagramComponent>
</div>
);
}
// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById("diagram") as HTMLElement);
root.render(<App />);NOTE
When using DataSource for layout generation, both DataBinding and HierarchicalTree modules must be injected into the diagram.
Troubleshooting
If the hierarchical tree layout does not render as expected, check the following common pitfalls:
-
Nodes are not arranged hierarchically or appear overlapping: Verify that the
HierarchicalTreemodule is injected viaInjectandlayout.typeis set to"HierarchicalTree". -
Diagram appears blank when using DataSource: Ensure that
dataSourceSettingsis configured with valididandparentIdvalues so the layout can resolve parent-child relationships. -
Data-driven nodes are not generated: Confirm that the
DataBindingmodule is injected in addition toHierarchicalTreewhen using a DataSource. -
Connectors are missing between nodes: Check that connectors are defined (or that
parentIdvalues resolve correctly in the data source) so the layout can link related nodes.