minop1205 / react-dnd-treeview

A draggable / droppable React-based treeview component. You can use render props to create each node freely.
MIT License
519 stars 69 forks source link

Data order #166

Closed gsavci closed 1 year ago

gsavci commented 1 year ago

When I drag elements, they appear in the right place. But when I print to the console, the order get mixed up. How can I sync data in the same order as on the screen? For example when I render my data it looks like it:

  Parent
     Children 1
     Children 2
              Sub-children

But when I write data to console, the order is :

Sub-children, Parent, Children 1, Children 2.

How can I sort data to make right order?

minop1205 commented 1 year ago

@gsavci The order of the tree is controlled by the sort property and insertDroppableFirst. See the README for details on these properties.

Setting both tofalse, as in the following example, will cause the order of the nodes to follow the order of the data array passed to the tree property.

      <Tree
        {... .someProps}
        tree={treeData}
        sort={false}
        insertDroppableFirst={false}
     />
gsavci commented 1 year ago

First of all thanks for your quick answer.

Both sort and insertDroppableFirst properties are already set false.

minop1205 commented 1 year ago

@gsavci

As it turns out, it is not possible to make the sequence of data exactly equivalent to the sequence on the display. This is due to the display logic of the tree and is intentional, not a bug.

If the sort property and insertDroppableFirst are false, then children with the same parent are compared for order of occurrence, but Indexes on other nodes are ignored.

This is fine on the tree display.

It is possible to move data to a position on the display rather than to the first index, but this would require a more complex implementation. This is why we are currently using a simple implementation.

For example, if all nodes are directly under the root, the order of the data is equal to the order in which they are displayed.

2022-11-03_18h05_36

So, moving File 3 to Folder 2-1 moves File 3 to the top of the data array.

2022-11-03_18h06_09

As a point of reference, I would like to ask, why is it necessary to match the data array to the order on the display? I myself don't understand the need for this and would like to know what use cases there are.

gsavci commented 1 year ago

I want to use the structure I created with this component as a tree structure in a different component. So I need to know the proper order of children of a node.

minop1205 commented 1 year ago

@gsavci

I believe that a good way to address this issue is to create a custom function to reorder the tree data into an arbitrary order.

Create a custom function as follows

type SortFn = (
  treeData: NodeModel<CustomData>[],
  sortedData: NodeModel<CustomData>[],
  parentId: NodeModel["id"]
) => void;

const sortTreeData: SortFn = (treeData, sortedData, parentId) => {
  const children = treeData.filter((node) => node.parent === parentId);

  children.forEach((node) => {
    sortedData.push(node);
    sortTreeData(treeData, sortedData, node.id);
  });
};

Apply this function in the onDrop callback.

  const handleDrop = (newTreeData: NodeModel<CustomData>[]) => {
    const sortedData = [];
    sortTreeData(newTreeData, sortedData, 0);
    setTreeData(sortedData);

    console.log(sortedData.map((node) => node.text));
  };

image

See below for an actual sample. https://codesandbox.io/s/issue-166-gqdrvy?file=/src/App.tsx:1033-1260

Please try it.