A React component for Drag-and-drop sortable representation of hierarchical data. Checkout the demo for a demonstration of some basic features. Checkout the storybook for advanced usage.
Install react-sortable-tree
using npm.
# NPM
npm install react-sortable-tree --save
# YARN
yarn add react-sortable-tree
ES6 and CommonJS builds are available with each distribution. For example:
// This only needs to be done once; probably during your application's bootstrapping process.
import 'react-sortable-tree/style.css';
// You can import the default tree with dnd context
import SortableTree from 'react-sortable-tree';
// Or you can import the tree without the dnd context as a named export. eg
import { SortableTreeWithoutDndContext as SortableTree } from 'react-sortable-tree';
// Importing from cjs (default)
import SortableTree from 'react-sortable-tree/dist/index.cjs.js';
import SortableTree from 'react-sortable-tree';
// Importing from esm
import SortableTree from 'react-sortable-tree/dist/index.esm.js';
import React, { Component } from 'react';
import SortableTree from 'react-sortable-tree';
import 'react-sortable-tree/style.css'; // This only needs to be imported once in your app
export default class Tree extends Component {
constructor(props) {
super(props);
this.state = {
treeData: [
{ title: 'Chicken', children: [{ title: 'Egg' }] },
{ title: 'Fish', children: [{ title: 'fingerline'}] }
],
};
}
render() {
return (
<div style={{ height: 400 }}>
<SortableTree
treeData={this.state.treeData}
onChange={treeData => this.setState({ treeData })}
/>
</div>
);
}
}
Need a hand turning your flat data into nested tree data? Want to perform add/remove operations on the tree data without creating your own recursive function? Check out the helper functions exported from tree-data-utils.js
.
getTreeFromFlatData
: Convert flat data (like that from a database) into nested tree data.getFlatDataFromTree
: Convert tree data back to flat data.addNodeUnderParent
: Add a node under the parent node at the given path.removeNode
: For a given path, get the node at that path, treeIndex, and the treeData with that node removed.removeNodeAtPath
: For a given path, remove the node and return the treeData.changeNodeAtPath
: Modify the node object at the given path.map
: Perform a change on every node in the tree.walk
: Visit every node in the tree in order.getDescendantCount
: Count how many descendants this node has.getVisibleNodeCount
: Count how many visible descendants this node has.getVisibleNodeInfoAtIndex
: Get the th visible node in the tree data.toggleExpandedForAll
: Expand or close every node in the tree.getNodeAtPath
: Get the node at the input path.insertNode
: Insert the input node at the specified depth and minimumTreeIndex.find
: Find nodes matching a search query in the tree.isDescendant
: Check if a node is a descendant of another node.getDepth
: Get the longest path in the tree.Using the theme
prop along with an imported theme module, you can easily override the default appearance with another standard one.
File Explorer | Full Node Drag | Minimalistic theme inspired from MATERIAL UI |
react-sortable-tree-theme-file-explorer | react-sortable-tree-theme-full-node-drag | react-sortable-tree-theme-minimal |
Github | NPM | Github |
Help Wanted - As the themes feature has just been enabled, there are very few (only two at the time of this writing) theme modules available. If you’ve customized the appearance of your tree to be especially cool or easy to use, I would be happy to feature it in this readme with a link to the Github repo and NPM page if you convert it to a theme. You can use my file explorer theme repo as a template to plug in your own stuff.
Browser | Works? |
---|---|
Chrome | Yes |
Firefox | Yes |
Safari | Yes |
IE 11 | Yes |
This issue may be related to an ongoing incompatibility between UglifyJS and Webpack’s behavior. See an explanation at create-react-app#2376.
The simplest way to mitigate this issue is by adding comparisons: false
to your Uglify config as seen here: https://github.com/facebookincubator/create-react-app/pull/2379/files
react-dnd only allows for one DragDropContext at a time (see: https://github.com/gaearon/react-dnd/issues/186). To get around this, you can import the context-less tree component via SortableTreeWithoutDndContext
.
// before
import SortableTree from 'react-sortable-tree';
// after
import { SortableTreeWithoutDndContext as SortableTree } from 'react-sortable-tree';
Please read the Code of Conduct. I actively welcome pull requests :)
After cloning the repository and running yarn install
inside, you can use the following commands to develop and build the project.
# Starts a webpack dev server that hosts a demo page with the component.
# It uses react-hot-loader so changes are reflected on save.
yarn start
# Start the storybook, which has several different examples to play with.
# Also hot-reloaded.
yarn run storybook
# Runs the library tests
yarn test
# Lints the code with eslint
yarn run lint
# Lints and builds the code, placing the result in the dist directory.
# This build is necessary to reflect changes if you're
# `npm link`-ed to this repository from another local project.
yarn run build
Pull requests are welcome!
Author: frontend-collective
Live Demo: https://frontend-collective.github.io/react-sortable-tree/
GitHub: https://github.com/frontend-collective/react-sortable-tree
#reactjs #javascript