React D3 Tree is a React component that lets you represent hierarchical data (e.g. ancestor trees, organisational structure, package dependencies) as an animated & interactive tree graph by leveraging D3's tree layout.
- Demo
- Installation
- Usage
- Props
- Node shapes
- Styling
- External data sources
- Using foreignObjects
- Recipes
- Current release: https://bkrem.github.io/react-d3-tree-demo/
yarn add react-d3-tree
# or
npm i --save react-d3-treeimport React from 'react';
import Tree from 'react-d3-tree';
const myTreeData = [
{
name: 'Top Level',
attributes: {
keyA: 'val A',
keyB: 'val B',
keyC: 'val C',
},
children: [
{
name: 'Level 2: A',
attributes: {
keyA: 'val A',
keyB: 'val B',
keyC: 'val C',
},
},
{
name: 'Level 2: B',
},
],
},
];
class MyComponent extends React.Component {
render() {
return (
{/* <Tree /> will fill width/height of its container; in this case `#treeWrapper` */}
<div id="treeWrapper" style={{width: '50em', height: '20em'}}>
<Tree data={myTreeData} />
</div>
);
}
}The nodeSvgShape prop allows specifying any SVG shape primitive to describe how the tree's nodes should be shaped.
Note:
nodeSvgShapeandcircleRadiusare mutually exclusive props.nodeSvgShapewill be used unless the legacycircleRadiusis specified.
For example, assuming we want to use squares instead of the default circles, we can do:
const svgSquare = {
shape: 'rect',
shapeProps: {
width: 20,
height: 20,
x: -10,
y: -10,
}
}
// ...
<Tree data={myTreeData} nodeSvgShape={svgSquare}>shapeProps is currently merged with node.circle/leafNode.circle (see Styling).
This means any properties passed in shapeProps will be overridden by properties with the same key in the node.circle/leafNode.circle style props.
This is to prevent breaking the legacy usage of circleRadius + styling via node/leafNode properties until it is deprecated fully in v2.
From v1.5.x onwards, it is therefore recommended to pass all node styling properties through shapeProps.
The tree's styles prop may be used to override any of the tree's default styling.
The following object shape is expected by styles:
{
links: <svgStyleObject>,
nodes: {
node: {
circle: <svgStyleObject>,
name: <svgStyleObject>,
attributes: <svgStyleObject>,
},
leafNode: {
circle: <svgStyleObject>,
name: <svgStyleObject>,
attributes: <svgStyleObject>,
},
},
}where <svgStyleObject> is any object containing CSS-like properties that are compatible with an <svg> element's style attribute, for example:
{
stroke: 'blue',
strokeWidth: 3,
}For more information on the SVG style attribute, check this out.
Statically hosted JSON or CSV files can be used as data sources via the additional treeUtil module.
import React from 'react';
import { Tree, treeUtil } from 'react-d3-tree';
const csvSource = 'https://raw.githubusercontent.com/bkrem/react-d3-tree/master/docs/examples/data/csv-example.csv';
constructor() {
super();
this.state = {
data: undefined,
};
}
componentWillMount() {
treeUtil.parseCSV(csvSource)
.then((data) => {
this.setState({ data })
})
.catch((err) => console.error(err));
}
class MyComponent extends React.Component {
render() {
return (
{/* <Tree /> will fill width/height of its container; in this case `#treeWrapper` */}
<div id="treeWrapper" style={{width: '50em', height: '20em'}}>
<Tree data={this.state.data} />
</div>
);
}
}For details regarding the treeUtil module, please check the module's API docs.
For examples of each data type that can be parsed with treeUtil, please check the data source examples.
⚠️ RequiresallowForeignObjectsprop to be set due to limited browser support: IE does not currently supportforeignObjectelements.
The SVG spec's foreignObject element allows foreign XML content to be rendered into the SVG namespace, unlocking the ability to use regular React components for elements of the tree graph.
The nodeLabelComponent prop provides a way to use a React component for each node's label. It accepts an object with the following signature:
{
render: ReactElement,
foreignObjectWrapper?: object
}renderis the XML React-D3-Tree will use to render each node's label.foreignObjectWrappercontains a set of attributes that should be passed to the<foreignObject />that wrapsnodeLabelComponent. For possible attributes please check the spec.
Note: foreignObjectWrapper will set its width and height attributes to whatever values nodeSize.x and nodeSize.y return by default.
To override this behaviour for each attribute, specify width and/or height properties for your foreignObjectWrapper.
Note: The ReactElement passed to render is cloned with its existing props and receives an additional nodeData object prop, containing information about the current node.
Assuming we have a React component NodeLabel and we want to avoid node's label overlapping with the node itself by moving its position along the Y-axis, we could implement nodeLabelComponent like so:
class NodeLabel extends React.PureComponent {
render() {
const {className, nodeData} = this.props
return (
<div className={className}>
<h2>{nodeData.name}</h2>
{nodeData._children &&
<button>{nodeData._collapsed ? 'Expand' : 'Collapse'}</button>
}
</div>
)
}
}
/* ... */
render() {
return (
<Tree
data={myTreeData}
allowForeignObjects
nodeLabelComponent={{
render: <NodeLabel className='myLabelComponentInSvg' />,
foreignObjectWrapper: {
y: 24
}
}}
/>
)
}