react-d3-tree vs react-flow-renderer vs react-organizational-chart vs react-graph-vis
React Graph and Tree Visualization Libraries Compared
react-d3-treereact-flow-rendererreact-organizational-chartreact-graph-visSimilar Packages:

React Graph and Tree Visualization Libraries Compared

react-d3-tree, react-flow-renderer, react-graph-vis, and react-organizational-chart are all React libraries for visualizing connected data structures, but they serve different use cases. react-d3-tree specializes in hierarchical tree diagrams using D3.js, ideal for file systems or family trees. react-flow-renderer (now rebranded as reactflow) focuses on interactive node-based editors and flow diagrams with custom node support. react-graph-vis wraps vis.js for general network graph visualization with physics-based layouts. react-organizational-chart is purpose-built for company org charts with predefined hierarchical styling. Each library has distinct strengths depending on whether you need strict hierarchy, free-form nodes, network graphs, or corporate structure display.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
react-d3-tree254,3941,196121 kB148a year agoMIT
react-flow-renderer225,21736,8741.6 MB107-MIT
react-organizational-chart78,142193494 kB153 years agoMIT
react-graph-vis20,658992-605 years agoMIT

React Graph and Tree Visualization Libraries Compared

When building React applications that need to display connected data β€” whether it's company hierarchies, workflow diagrams, or network graphs β€” choosing the right visualization library matters. Each of these four packages (react-d3-tree, react-flow-renderer, react-graph-vis, react-organizational-chart) solves similar problems but with different trade-offs. Let's break down how they actually work in practice.

🌳 Tree Structure Support: Hierarchical vs Free-Form

react-d3-tree renders strict parent-child tree structures with automatic layout.

import Tree from 'react-d3-tree';

const data = {
  name: 'CEO',
  children: [
    {
      name: 'CTO',
      children: [
        { name: 'Developer' },
        { name: 'Designer' }
      ]
    },
    {
      name: 'CFO',
      children: [{ name: 'Accountant' }]
    }
  ]
};

<Tree data={data} orientation="vertical" />;

react-flow-renderer treats everything as free-form nodes with optional connections.

import ReactFlow from 'react-flow-renderer';

const nodes = [
  { id: '1', position: { x: 0, y: 0 }, data: { label: 'CEO' } },
  { id: '2', position: { x: 0, y: 100 }, data: { label: 'CTO' } }
];

const edges = [
  { id: 'e1-2', source: '1', target: '2' }
];

<ReactFlow nodes={nodes} edges={edges} />;

react-graph-vis uses network graph data format with nodes and edges arrays.

import { Graph } from 'react-graph-vis';

const graph = {
  nodes: [
    { id: 1, label: 'CEO' },
    { id: 2, label: 'CTO' }
  ],
  edges: [
    { from: 1, to: 2 }
  ]
};

const options = { layout: { hierarchical: { enabled: true } } };

<Graph graph={graph} options={options} />;

react-organizational-chart provides pre-built org chart components with nested children.

import { OrganizationChart } from 'react-organizational-chart';

<OrganizationChart label="CEO">
  <OrganizationChart label="CTO">
    <OrganizationChart label="Developer" />
    <OrganizationChart label="Designer" />
  </OrganizationChart>
  <OrganizationChart label="CFO">
    <OrganizationChart label="Accountant" />
  </OrganizationChart>
</OrganizationChart>;

🎨 Custom Node Rendering: Fixed vs Flexible

react-d3-tree allows custom node HTML through render props but keeps tree layout fixed.

import Tree from 'react-d3-tree';

const renderCustomNode = ({ nodeDatum }) => (
  <foreignObject width={150} height={40}>
    <div className="custom-node">
      <strong>{nodeDatum.name}</strong>
    </div>
  </foreignObject>
);

<Tree data={data} renderCustomNodeElement={renderCustomNode} />;

react-flow-renderer gives full control over node appearance and behavior.

import ReactFlow, { useNodesState } from 'react-flow-renderer';

const CustomNode = ({ data }) => (
  <div className="custom-node">
    <div className="avatar">{data.avatar}</div>
    <div className="label">{data.label}</div>
    <button onClick={data.onAction}>Action</button>
  </div>
);

const nodeTypes = { custom: CustomNode };

<ReactFlow nodeTypes={nodeTypes} nodes={nodes} />;

react-graph-vis supports custom node styling through vis.js options.

import { Graph } from 'react-graph-vis';

const graph = {
  nodes: [
    {
      id: 1,
      label: 'CEO',
      shape: 'image',
      image: '/avatar.png',
      font: { size: 16, color: '#000' }
    }
  ],
  edges: [{ from: 1, to: 2 }]
};

const options = {
  nodes: {
    shape: 'box',
    color: { background: '#97C2FC' }
  }
};

<Graph graph={graph} options={options} />;

react-organizational-chart allows custom node content through children prop.

import { OrganizationChart } from 'react-organizational-chart';

<OrganizationChart
  label="CEO"
  nodeContent={
    <div className="org-node">
      <img src="/avatar.png" alt="CEO" />
      <span>John Smith</span>
    </div>
  }
>
  <OrganizationChart label="CTO" />
</OrganizationChart>;

πŸ”— Edge and Connection Handling

react-d3-tree automatically draws edges between parent and child nodes.

import Tree from 'react-d3-tree';

// Edges are implicit in the tree structure
const data = {
  name: 'Root',
  children: [
    { name: 'Child 1' },
    { name: 'Child 2' }
  ]
};

<Tree
  data={data}
  pathFunc="step"
  translate={{ x: 500, y: 200 }}
/>;

react-flow-renderer supports multiple edge types with custom styling.

import ReactFlow from 'react-flow-renderer';

const edges = [
  {
    id: 'e1-2',
    source: '1',
    target: '2',
    type: 'smoothstep',
    style: { stroke: '#2563eb', strokeWidth: 2 },
    label: 'Reports To'
  },
  {
    id: 'e1-3',
    source: '1',
    target: '3',
    type: 'bezier',
    animated: true
  }
];

<ReactFlow edges={edges} />;

react-graph-vis provides physics-based edge rendering with arrows and labels.

import { Graph } from 'react-graph-vis';

const graph = {
  nodes: [{ id: 1, label: 'A' }, { id: 2, label: 'B' }],
  edges: [
    {
      from: 1,
      to: 2,
      arrows: 'to',
      label: 'Connection',
      color: { color: '#848484', highlight: '#848484' }
    }
  ]
};

<Graph graph={graph} options={{ edges: { smooth: true } }} />;

react-organizational-chart draws connecting lines automatically between nested components.

import { OrganizationChart } from 'react-organizational-chart';

// Lines are drawn automatically between parent and child
<OrganizationChart label="Manager" lineColor="#2563eb" lineWidth={2}>
  <OrganizationChart label="Employee 1" />
  <OrganizationChart label="Employee 2" />
</OrganizationChart>;

πŸ–±οΈ User Interaction: Read-Only vs Editable

react-d3-tree focuses on viewing with zoom, pan, and node collapse.

import Tree from 'react-d3-tree';

<Tree
  data={data}
  zoomable={true}
  translate={{ x: 500, y: 200 }}
  onNodeClick={(nodeData) => {
    console.log('Node clicked:', nodeData);
  }}
  collapsible={true}
/>;

react-flow-renderer built for editing with drag, drop, and connection creation.

import ReactFlow, {
  useNodesState,
  useEdgesState,
  addEdge
} from 'react-flow-renderer';

function FlowEditor() {
  const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes);
  const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges);

  const onConnect = (params) => setEdges((eds) => addEdge(params, eds));

  return (
    <ReactFlow
      nodes={nodes}
      edges={edges}
      onNodesChange={onNodesChange}
      onEdgesChange={onEdgesChange}
      onConnect={onConnect}
      connectionLineType="smoothstep"
      fitView
    />
  );
}

react-graph-vis supports manipulation mode for adding/moving nodes.

import { Graph } from 'react-graph-vis';

const options = {
  manipulation: {
    enabled: true,
    addNode: function (data, callback) {
      data.label = prompt('Enter node label');
      callback(data);
    },
    editEdge: true,
    deleteNode: true,
    deleteEdge: true
  },
  physics: { enabled: true }
};

<Graph graph={graph} options={options} getNetwork={(network) => {
  // Access vis.js network instance for advanced control
}} />;

react-organizational-chart primarily read-only with expand/collapse.

import { OrganizationChart } from 'react-organizational-chart';

<OrganizationChart
  label="CEO"
  onNodeClick={(node) => {
    console.log('Org node clicked:', node);
  }}
  collapsible={true}
>
  <OrganizationChart label="CTO" collapsed={false}>
    <OrganizationChart label="Developer" />
  </OrganizationChart>
</OrganizationChart>;

πŸ“ Layout and Positioning

react-d3-tree uses D3's tree layout algorithm with automatic spacing.

import Tree from 'react-d3-tree';

<Tree
  data={data}
  orientation="vertical"
  separation={{ siblings: 1, nonSiblings: 2 }}
  translate={{ x: 400, y: 100 }}
  scaleExtent={{ min: 0.5, max: 2 }}
/>;

react-flow-renderer requires manual positioning or auto-layout libraries.

import ReactFlow from 'react-flow-renderer';
import { useLayoutNodes } from '@reactflow/core';

// Manual positioning
const nodes = [
  { id: '1', position: { x: 0, y: 0 }, data: { label: 'Start' } },
  { id: '2', position: { x: 200, y: 100 }, data: { label: 'Process' } }
];

// Or use auto-layout library like dagre
<ReactFlow nodes={nodes} fitView />;

react-graph-vis offers multiple layout algorithms including physics and hierarchical.

import { Graph } from 'react-graph-vis';

const options = {
  layout: {
    hierarchical: {
      enabled: true,
      direction: 'UD',
      sortMethod: 'hubsize',
      levelSeparation: 150,
      nodeSpacing: 100
    }
  },
  physics: {
    enabled: false // Disable for stable hierarchical layout
  }
};

<Graph graph={graph} options={options} />;

react-organizational-chart uses fixed vertical/horizontal spacing.

import { OrganizationChart } from 'react-organizational-chart';

<OrganizationChart
  label="Root"
  lineColor="#ccc"
  lineWidth={2}
  nodeSpacing={50}
  verticalSpacing={80}
>
  <OrganizationChart label="Child 1" />
  <OrganizationChart label="Child 2" />
</OrganizationChart>;

⚠️ Package Status and Maintenance

react-d3-tree remains actively maintained with regular updates. The API is stable and well-documented. Suitable for production use in tree visualization scenarios.

react-flow-renderer has been rebranded to reactflow (package: @xyflow/react). The old package name still works but new projects should use the updated name. Check migration guides when starting fresh.

// Old (still works)
import ReactFlow from 'react-flow-renderer';

// New (recommended)
import ReactFlow from '@xyflow/react';

react-graph-vis wraps vis.js, which has seen reduced maintenance activity. The React wrapper itself receives occasional updates but depends on vis.js stability. Evaluate long-term support needs before committing to large projects.

react-organizational-chart is a smaller, focused library with less frequent updates. Works well for simple org charts but may lack features for complex requirements. Consider if your needs might outgrow its capabilities.

🌱 When Not to Use These Libraries

These visualization tools excel in their niches, but consider alternatives when:

  • You need high-performance rendering for 1000+ nodes: Look into canvas-based solutions like react-konva or WebGL libraries
  • You require real-time collaborative editing: Consider specialized libraries like tldraw or build custom solutions
  • Your data is simple enough for basic lists or tables: Don't add visualization complexity unnecessarily
  • You need mobile-first touch interactions: Test thoroughly as some libraries have limited mobile support

πŸ“Œ Summary Table

Featurereact-d3-treereact-flow-rendererreact-graph-visreact-organizational-chart
Best ForTree hierarchiesNode editorsNetwork graphsOrg charts
LayoutAutomatic treeManual/autoPhysics/hierarchicalFixed org layout
Custom NodesLimitedFull controlModeratePre-styled
EditableRead-onlyFull editingManipulation modeRead-only
EdgesAuto (tree)Custom typesCustom stylingAuto (hierarchy)
MaintenanceActiveRebranded (reactflow)SlowedModerate

πŸ’‘ Final Recommendation

Think about your data structure and user needs first:

  • Strict parent-child hierarchy with viewing focus? β†’ react-d3-tree
  • Interactive diagram editor with custom nodes? β†’ react-flow-renderer (or @xyflow/react)
  • Network graphs with many-to-many relationships? β†’ react-graph-vis
  • Company org charts with minimal setup? β†’ react-organizational-chart

Important Note: For new projects requiring node-based editing, prefer @xyflow/react over react-flow-renderer as it's the actively maintained version. The core API remains similar but benefits from ongoing development.

All four libraries can produce professional results when matched to the right use case. The key is understanding whether you need strict hierarchy, free-form layouts, network visualization, or purpose-built org charts before making your choice.

How to Choose: react-d3-tree vs react-flow-renderer vs react-organizational-chart vs react-graph-vis

  • react-d3-tree:

    Choose react-d3-tree when you need clean, collapsible tree structures with minimal setup. It excels at displaying hierarchical data like file systems, decision trees, or family trees where parent-child relationships are strict. The D3-based rendering provides smooth animations and zoom/pan capabilities out of the box. However, it lacks support for custom node interactivity beyond basic click events, making it less suitable for complex editor interfaces.

  • react-flow-renderer:

    Choose react-flow-renderer (now reactflow) when building node-based editors, workflow designers, or diagramming tools. It offers the most flexibility for custom nodes, edges, and user interactions like drag-and-drop. The library supports multiple edge types, connection validation, and mini-maps. Note that the package has been rebranded to @xyflow/react, so new projects should consider the updated name. Best for applications where users create or modify graph structures.

  • react-organizational-chart:

    Choose react-organizational-chart when you specifically need company org charts or similar hierarchical displays with minimal customization. It provides pre-styled components optimized for showing reporting structures with photos, titles, and expandable branches. Less flexible than other options but faster to implement for standard org chart requirements. Not suitable for general graph or tree visualization beyond organizational hierarchies.

  • react-graph-vis:

    Choose react-graph-vis when you need physics-based network graphs with automatic layout algorithms. It wraps vis.js, providing proven graph visualization with clustering, hierarchical layouts, and manipulation options. Ideal for social networks, dependency graphs, or any scenario where nodes have many-to-many relationships. Be aware that vis.js maintenance has slowed, so evaluate long-term support needs before committing to production use.

README for react-d3-tree

React D3 Tree

build status coverage status npm package npm package: downloads monthly npm package: minzipped size npm package: types code style: prettier

πŸ‘Ύ Playground

πŸ“– API Documentation (v3)

React D3 Tree is a React component that lets you represent hierarchical data (e.g. family trees, org charts, file directories) as an interactive tree graph with minimal setup, by leveraging D3's tree layout.

Upgrading from v1? Check out the v2 release notes.

Legacy v1 docs

Contents

Installation

npm i --save react-d3-tree

Usage

import React from 'react';
import Tree from 'react-d3-tree';

// This is a simplified example of an org chart with a depth of 2.
// Note how deeper levels are defined recursively via the `children` property.
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 />` will fill width/height of its container; in this case `#treeWrapper`.
    <div id="treeWrapper" style={{ width: '50em', height: '20em' }}>
      <Tree data={orgChart} />
    </div>
  );
}

Props

For details on all props accepted by Tree, check out the TreeProps reference docs.

The only required prop is data, all other props on Tree are optional/pre-defined (see "Default value" on each prop definition).

Working with the default Tree

react-d3-tree provides default implementations for Tree's nodes & links, which are intended to get you up & running with a working tree quickly.

This section is focused on explaining how to provide data, styles and event handlers for the default Tree implementation.

Need more fine-grained control over how nodes & links appear/behave? Check out the Customizing the Tree section below.

Providing data

By default, Tree expects each node object in data to implement the RawNodeDatum interface:

interface RawNodeDatum {
  name: string;
  attributes?: Record<string, string | number | boolean>;
  children?: RawNodeDatum[];
}

The orgChart example in the Usage section above is an example of this:

  • Every node has at least a name. This is rendered as the node's primary label.
  • Some nodes have attributes defined (the CEO node does not). The key-value pairs in attributes are rendered as a list of secondary labels.
  • Nodes can have further RawNodeDatum objects nested inside them via the children key, creating a hierarchy from which the tree graph can be generated.

Styling Nodes

Tree provides the following props to style different types of nodes, all of which use an SVG circle by default:

  • rootNodeClassName - applied to the root node.
  • branchNodeClassName - applied to any node with 1+ children.
  • leafNodeClassName - applied to any node without children.

To visually distinguish these three types of nodes from each other by color, we could provide each with their own class:

/* custom-tree.css */

.node__root > circle {
  fill: red;
}

.node__branch > circle {
  fill: yellow;
}

.node__leaf > circle {
  fill: green;
  /* Let's also make the radius of leaf nodes larger */
  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>
  );
}

For more details on the className props for nodes, see the TreeProps reference docs.

Styling Links

Tree provides the pathClassFunc property to pass additional classNames to every link to be rendered.

Each link calls pathClassFunc with its own TreeLinkDatum and the tree's current orientation. Tree expects pathClassFunc to return a className string.

function StyledLinksTree() {
  const getDynamicPathClass = ({ source, target }, orientation) => {
    if (!target.children) {
      // Target node has no children -> this link leads to a leaf node.
      return 'link__to-leaf';
    }

    // Style it as a link connecting two branch nodes by default.
    return 'link__to-branch';
  };

  return (
    <Tree
      data={data}
      // Statically apply same className(s) to all links
      pathClassFunc={() => 'custom-link'}
      // Want to apply multiple static classes? `Array.join` is your friend :)
      pathClassFunc={() => ['custom-link', 'extra-custom-link'].join(' ')}
      // Dynamically determine which `className` to pass based on the link's properties.
      pathClassFunc={getDynamicPathClass}
    />
  );
}

For more details, see the PathClassFunction reference docs.

Event Handlers

Tree exposes the following event handler callbacks by default:

Note: Nodes are expanded/collapsed whenever onNodeClick fires. To prevent this, set the collapsible prop to false.
onNodeClick will still fire, but it will not change the target node's expanded/collapsed state.

Customizing the Tree

renderCustomNodeElement

The renderCustomNodeElement prop accepts a custom render function that will be used for every node in the tree.

Cases where you may find rendering your own Node element useful include:

  • Using a different SVG tag for your nodes (instead of the default <circle>) - Example (codesandbox.io)
  • Gaining fine-grained control over event handling (e.g. to implement events not covered by the default API) - Example (codesandbox.io)
  • Building richer & more complex nodes/labels by leveraging the foreignObject tag to render HTML inside the SVG namespace - Example (codesandbox.io)

pathFunc

The pathFunc prop accepts a predefined PathFunctionOption enum or a user-defined PathFunction.

By changing or providing your own pathFunc, you are able to change how links between nodes of the tree (which are SVG path tags under the hood) are drawn.

The currently available enums are:

  • diagonal (default)
  • elbow
  • straight
  • step

Want to see how each option looks? Try them out on the playground.

Providing your own pathFunc

If none of the available path functions suit your needs, you're also able to provide a custom PathFunction:

function CustomPathFuncTree() {
  const straightPathFunc = (linkDatum, orientation) => {
    const { source, target } = linkDatum;
    return 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}
      // Passing `straight` function as a custom `PathFunction`.
      pathFunc={straightPathFunc}
    />
  );
}

For more details, see the PathFunction reference docs.

Development

Setup

To set up react-d3-tree for local development, clone the repo and follow the steps below:

# 1. Set up the library, create a reference to it for symlinking.
cd react-d3-tree
npm i
npm link

# 2. Set up the demo/playground, symlink to the local copy of `react-d3-tree`.
cd demo
npm i
npm link react-d3-tree

Tip: If you'd prefer to use your own app for development instead of the demo, simply run npm link react-d3-tree in your app's root folder instead of the demo's :)

Hot reloading

npm run build:watch

If you're using react-d3-tree/demo for development, open up another terminal window in the demo directory and call:

npm start

Contributors

A huge thank you to all the contributors, as well as users who have opened issues with thoughtful suggestions and feedback.