Search code examples
reactjsreact-hooksreact-hook-formuse-refreact-beautiful-dnd

How to work Drag-and-drop for nested array in useFieldArray


I am trying to implement the drag-n-drop feature on a nested array of inputs. I am using react-beautiful-dnd and react-hook-form libraries: useFieldArray hook to manage the form and useController hook for controlled input.

The problem I am facing is when i try to reorder any child input, change happens in the last item only. here is a sandbox.

To reproduce the issue, you need to add at least 2 top-level inputs along with 2 nested inputs for each of those. Next try to reorder the nested inputs of the 1st top-level item. As a result, child inputs of the 2nd item would change their positions, while the initially dragged inputs would revert back to their original position. see GIF

I tried to pass ref to nested inputs and used useImperativeHandle hook to expose move method of useFieldArray hook from child component to reorder. But everytime only the last child gets reordered


Solution

  • SOLVED

    I was using the same ref for my nested field array to store reorder child function therefore when appending a new nested child field array, it was overriding the reorder function and only moving items belonging to the last nested field array.

    To solve this, I had to pass a function instead of ref to the nested fields which creates different ref for each

    function Parent () {
      const childrenRef = useRef({});
      const setReorder = useCallback(
      (index, reorderCallback) => {
        childrenRef.current[index] = reorderCallback;
      },
      [childrenRef]
     );
      ...
    
      return (
       <Child
         setReorder={setReorder}
       />
     )
    }
    
    function Child ({ setReorder, nestIndex }) {
      useEffect(() => {
        setReorder(`child-${nestIndex}`, (from, to) => {
          move(from, to);
        });
      }, [nestIndex, setReorder, move]);
    }
    

    Here is the working sandbox