Interactive tree diagram with draggable nodes on a computer screen

Rooted in Flexibility: Mastering Dynamic UIs with React Sortable Tree

The Orange Cat
The Orange Cat

React Sortable Tree is a powerful and flexible library that allows developers to create interactive, draggable tree structures in React applications. It’s perfect for building file explorers, organizational charts, nested category systems, or any other hierarchical data representation that requires user interaction.

Key Features

React Sortable Tree comes packed with a variety of features that make it a versatile choice for developers:

  • Drag-and-drop functionality: Users can easily reorder and restructure the tree by dragging nodes.
  • Customizable node rendering: Developers can define how each node looks and behaves.
  • Virtual rendering: Large trees remain performant through efficient rendering of only visible nodes.
  • Keyboard navigation: Enhances accessibility by allowing users to navigate the tree using keyboard inputs.
  • Search functionality: Built-in search capability to filter and highlight nodes.
  • Theming support: Easily customize the appearance to match your application’s design.

Getting Started

Installation

To start using React Sortable Tree in your project, you’ll need to install it along with its peer dependencies. You can do this using npm or yarn:

Using npm:

npm install react-sortable-tree react-dnd react-dnd-html5-backend

Using yarn:

yarn add react-sortable-tree react-dnd react-dnd-html5-backend

Basic Usage

Let’s dive into a simple example to get you started with React Sortable Tree:

import React, { useState } from 'react';
import SortableTree from 'react-sortable-tree';
import 'react-sortable-tree/style.css';

const BasicTree: React.FC = () => {
  const [treeData, setTreeData] = useState([
    { title: 'Chicken', children: [{ title: 'Egg' }] },
    { title: 'Fish', children: [{ title: 'fingerling' }] },
  ]);

  return (
    <div style={{ height: 400 }}>
      <SortableTree
        treeData={treeData}
        onChange={(treeData) => setTreeData(treeData)}
      />
    </div>
  );
};

export default BasicTree;

In this example, we create a simple tree structure with two parent nodes, each containing a child node. The onChange prop allows us to update the tree data when nodes are moved or modified.

Advanced Usage

Custom Node Rendering

One of the most powerful features of React Sortable Tree is the ability to customize how nodes are rendered. This allows you to create unique and interactive tree structures tailored to your specific needs.

import React, { useState } from 'react';
import SortableTree, { TreeItem } from 'react-sortable-tree';
import 'react-sortable-tree/style.css';

const CustomNodeTree: React.FC = () => {
  const [treeData, setTreeData] = useState([
    { title: 'Documents', children: [{ title: 'Report.docx' }] },
    { title: 'Pictures', children: [{ title: 'Vacation.jpg' }] },
  ]);

  const renderNode = ({ node, path }: { node: TreeItem; path: number[] }) => (
    <div style={{ display: 'flex', alignItems: 'center' }}>
      <span>{node.title}</span>
      <button onClick={() => alert(`Node path: ${path}`)}>Info</button>
    </div>
  );

  return (
    <div style={{ height: 400 }}>
      <SortableTree
        treeData={treeData}
        onChange={(treeData) => setTreeData(treeData)}
        generateNodeProps={({ node, path }) => ({
          title: renderNode({ node, path }),
        })}
      />
    </div>
  );
};

export default CustomNodeTree;

This example demonstrates how to use the generateNodeProps prop to customize node rendering. We’ve added an “Info” button to each node that displays the node’s path when clicked.

Handling External Drops

React Sortable Tree also supports handling drops from external sources, which can be useful for adding new items to the tree from elsewhere in your application.

import React, { useState } from 'react';
import SortableTree, { TreeItem } from 'react-sortable-tree';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import 'react-sortable-tree/style.css';

const ExternalDropTree: React.FC = () => {
  const [treeData, setTreeData] = useState<TreeItem[]>([
    { title: 'Root', children: [] },
  ]);

  const handleDrop = (newTreeData: TreeItem[], dropInfo: any) => {
    if (dropInfo.dropTargetType === 'tree') {
      const newNode = { title: 'New Item' };
      newTreeData.splice(dropInfo.targetIndex, 0, newNode);
      setTreeData(newTreeData);
    }
  };

  return (
    <DndProvider backend={HTML5Backend}>
      <div style={{ display: 'flex', height: 400 }}>
        <div
          style={{
            width: 100,
            border: '1px solid black',
            padding: 10,
            marginRight: 10,
          }}
          draggable
          onDragStart={(e) => e.dataTransfer.setData('text/plain', '')}
        >
          Drag me
        </div>
        <SortableTree
          treeData={treeData}
          onChange={setTreeData}
          dndType="yourNodeType"
          onDrop={handleDrop}
        />
      </div>
    </DndProvider>
  );
};

export default ExternalDropTree;

This example sets up a draggable element outside the tree. When dropped onto the tree, it creates a new node at the drop location.

Optimizing Performance

When working with large trees, performance can become a concern. React Sortable Tree offers several ways to optimize rendering and interaction:

Virtual Rendering

By default, React Sortable Tree uses virtual rendering to efficiently handle large datasets. This means only the visible nodes are rendered, significantly improving performance for trees with many nodes.

Row Height Calculation

For even better performance, you can provide a rowHeight prop to avoid calculating heights for each row:

<SortableTree
  treeData={treeData}
  onChange={setTreeData}
  rowHeight={62} // Fixed height for each row
/>

Disabling Animations

If smooth animations aren’t necessary for your use case, you can disable them to further improve performance:

<SortableTree
  treeData={treeData}
  onChange={setTreeData}
  slideRegionSize={0} // Disables animations
/>

Conclusion

React Sortable Tree offers a robust solution for creating interactive tree structures in React applications. Its flexibility in customization, coupled with powerful features like drag-and-drop functionality and virtual rendering, makes it an excellent choice for developers looking to implement complex hierarchical UIs.

While the library is no longer actively maintained, its stable version continues to provide value for many projects. As you cultivate dynamic hierarchies in your applications, React Sortable Tree remains a solid foundation for creating user-friendly and interactive interfaces.

Remember to consider performance optimizations when working with large datasets, and don’t hesitate to explore the library’s extensive API to tailor the tree component to your specific needs. Happy coding, and may your tree structures grow tall and strong!

Comments