5

I use react-dnd together with a react maui tree. My goal is to drag multiple items at once.

My approach is to store all the selected nodes from the tree in useState as an array of ids(strings). On Click on a node the state is updated and I can successfully select multiple nodes.

The problems begin on drag. The item is not updated.

// returns the state
// initially e.g. ["4372"] later it should return the correct result
const getState = () => {
    return selectedTreeNodes
  }  
const [, drag] = useDrag(() => ({
    type: "el",
    item: getState(),
    end: (item, monitor) => {
      const dropResult = monitor.getDropResult<DropResult>();
      if (item && dropResult) {
        alert(`You dropped ${item} ${selectedTreeNodes} into ${dropResult}!`);
      }
      console.log("DROPPED", item, "SELECTEDFIELDS", getState()); // all these are only logging the old state
    },
    collect: (monitor) => ({
      isDragging: monitor.isDragging(),
      handlerId: monitor.getHandlerId(),
    }),
  }));

I tried different approaches. The selectedTreeNodes are the ids. They are passed down from the parent component and in there they are the state. When I click on the parent node, the tree opens, and the item gets the id from the first selected parent node.

After changing the selection and starting the drag, the item doesn´t get updated anymore and hence I don´t get the updated ids but only the first one. The state itself updates correctly.

Any suggestions?

Peer
  • 189
  • 1
  • 8

2 Answers2

6

As stated in the comment, adding the selectedTreeNodes from the useState into the dependency array of the useDrag will do the magic.

Below the code (bit shorter than in the question) for people who might have the same problem:

  const [, drag] = useDrag(
    () => ({
      type: "el",
      item: selectedTreeNodes,
      collect: (monitor) => ({
        isDragging: monitor.isDragging(),
        handlerId: monitor.getHandlerId(),
      }),
    }),
    [selectedTreeNodes] // DEPENDENCY ARRAY HERE
  );
Peer
  • 189
  • 1
  • 8
2

try to switch useMemo instead of useState and use dependencies in useMemo

useMemo(() => {
  // code
}, [dependency])

and on change dependency you will trigger whole memo same is for useCallback but useCallback return function and useMemo return variable

Abdulrahim Klis
  • 388
  • 3
  • 9
  • Thanks a lot. Even though I don´t fully understand how to use your comment I figured out how to do it. The docs are saying on the useDrag, that you can add some dependency array which behaves like the useMemo. So putting the selectedTreeNodes from the useState in the dependency array did the magic! – Peer Mar 05 '22 at 08:38