Playground · API reference (v3)
React D3 Tree is a React component that renders hierarchical data, such as family trees, org charts, and file directories, as an interactive tree graph. It uses the tree layout from D3.
- Install
- Quick start
- Data format
- Props
- Style nodes
- Style links
- Handle events
- Render custom nodes
- Change how links are drawn
- Contributing
- Older versions
npm install react-d3-treeReact D3 Tree supports React 16, 17, 18, and 19, and ships its own TypeScript types.
import React from 'react';
import Tree from 'react-d3-tree';
// Each node has a `name`, optional `attributes`, and optional `children`.
const orgChart = {
name: 'CEO',
children: [
{
name: 'Manager',
attributes: { department: 'Production' },
children: [
{
name: 'Foreman',
attributes: { department: 'Fabrication' },
children: [{ name: 'Worker' }],
},
{
name: 'Foreman',
attributes: { department: 'Assembly' },
children: [{ name: 'Worker' }],
},
],
},
],
};
export default function OrgChartTree() {
return (
// `Tree` fills the width and height of its container.
<div id="treeWrapper" style={{ width: '50em', height: '20em' }}>
<Tree data={orgChart} />
</div>
);
}Tree expects data to be a node object that matches the RawNodeDatum interface:
interface RawNodeDatum {
name: string;
attributes?: Record<string, string | number | boolean>;
children?: RawNodeDatum[];
}nameis required. The default node shows it as the node's main label.attributesis optional. The default node lists each key-value pair below the name.childrenholds the node's child nodes, each of which is also aRawNodeDatum.
data also accepts an array, but Tree renders only its first element.
data is the only required prop. For every prop, its type, and its default value, see the TreeProps reference.
By default, each node is an SVG circle. To style nodes by their position in the tree, pass a class name to one or more of these props:
rootNodeClassName: the root node.branchNodeClassName: nodes with children.leafNodeClassName: nodes without children.
For example, to give each kind of node its own color:
/* custom-tree.css */
.node__root > circle {
fill: red;
}
.node__branch > circle {
fill: yellow;
}
.node__leaf > circle {
fill: green;
/* Leaf nodes also get a larger radius. */
r: 40;
}import React from 'react';
import Tree from 'react-d3-tree';
import './custom-tree.css';
export default function StyledNodesTree() {
return (
<div id="treeWrapper" style={{ width: '50em', height: '20em' }}>
<Tree
data={data}
rootNodeClassName="node__root"
branchNodeClassName="node__branch"
leafNodeClassName="node__leaf"
/>
</div>
);
}To add class names to links, pass a function to pathClassFunc. Tree calls it for each link with the link's TreeLinkDatum and the tree's orientation, and adds the returned string to the link's class attribute.
To give every link the same classes, return a fixed string:
<Tree data={data} pathClassFunc={() => 'custom-link extra-custom-link'} />To pick classes per link, read the link's source and target nodes:
function StyledLinksTree() {
const getDynamicPathClass = ({ source, target }, orientation) => {
// The target has no children, so this link leads to a leaf node.
if (!target.children) {
return 'link__to-leaf';
}
return 'link__to-branch';
};
return <Tree data={data} pathClassFunc={getDynamicPathClass} />;
}Tree accepts these event handlers:
onNodeClickonNodeMouseOveronNodeMouseOutonLinkClickonLinkMouseOveronLinkMouseOutonUpdate: runs after each zoom or pan, and after each update of the tree, such as a node toggle.
A click on a default node's circle expands or collapses the node, then calls onNodeClick. To keep nodes from expanding or collapsing, set collapsible to false; onNodeClick still runs.
To center a node in view when it's clicked, pass the container's size to dimensions.
To replace the default node, pass a render function to renderCustomNodeElement. Tree calls it for every node with CustomNodeElementProps and renders the SVG element it returns.
A custom node controls its own clicks. To keep the default behavior, call toggleNode to expand or collapse the node, and onNodeClick to run your onNodeClick handler and, if you set dimensions, center the node.
Example: a different SVG element
This node draws a square instead of a circle and keeps the default click behavior.
const renderRectNode = ({ nodeDatum, toggleNode, onNodeClick }) => (
<g>
<rect
width="20"
height="20"
x="-10"
y="-10"
onClick={evt => {
toggleNode();
onNodeClick(evt);
}}
/>
<text x="20">{nodeDatum.name}</text>
</g>
);
<Tree data={data} renderCustomNodeElement={renderRectNode} />;Example: custom event handlers
This node splits the click behavior: a click on the label expands or collapses the node, and a click on the circle calls onNodeClick. nodeDatum.__rd3t.collapsed tells you whether the node is collapsed.
const renderLabelToggleNode = ({ nodeDatum, toggleNode, onNodeClick }) => (
<g>
<circle r="15" onClick={onNodeClick} />
<text x="20" onClick={toggleNode}>
{nodeDatum.name}
{nodeDatum.children && (nodeDatum.__rd3t.collapsed ? ' (+)' : ' (-)')}
</text>
</g>
);
<Tree
data={data}
renderCustomNodeElement={renderLabelToggleNode}
onNodeClick={node => console.log(node.data.name)}
/>;Example: HTML inside nodes
SVG can't hold HTML elements directly. To render HTML in a node, wrap it in a foreignObject element. If the HTML holds inputs or other controls, set hasInteractiveNodes so that dragging and zooming don't get in their way.
const renderHtmlNode = ({ nodeDatum, toggleNode }) => (
<g>
<circle r="15" />
<foreignObject width="200" height="100" x="20" y="-50">
<div style={{ border: '1px solid black', backgroundColor: '#dedede' }}>
<h3 style={{ textAlign: 'center' }}>{nodeDatum.name}</h3>
{nodeDatum.children && (
<button type="button" style={{ width: '100%' }} onClick={toggleNode}>
{nodeDatum.__rd3t.collapsed ? 'Expand' : 'Collapse'}
</button>
)}
</div>
</foreignObject>
</g>
);
<Tree data={data} renderCustomNodeElement={renderHtmlNode} hasInteractiveNodes />;Each link is an SVG path. To change its shape, set pathFunc to one of these options:
diagonal(default)elbowstraightstep
To compare them, try each one in the playground.
For a shape the options don't cover, pass your own PathFunction. Tree calls it for each link with the link's TreeLinkDatum and the tree's orientation, and uses the returned string as the path's d attribute. This example draws straight lines:
function CustomPathFuncTree() {
const straightPathFunc = ({ source, target }, orientation) =>
orientation === 'horizontal'
? `M${source.y},${source.x}L${target.y},${target.x}`
: `M${source.x},${source.y}L${target.x},${target.y}`;
return <Tree data={data} pathFunc={straightPathFunc} />;
}In a horizontal tree, x and y swap: a node's y is its horizontal position.
To set up the repo, run the playground, and submit changes, see CONTRIBUTING.md. Thanks to all contributors and to everyone who opens issues with suggestions and feedback.
- v2 release notes, which list the breaking changes from v1.
- v1 docs.