Giii
Giii

Reputation: 7

How to dynamically update drag ghost image text during drag operation in React?

I'm trying to update the text of a custom drag ghost image while dragging over specific elements. However, the ghost image text doesn't update even though the state changes.

Here's my code:

export const DndPage = () => {
  const handleOnDrag = useCallback((event) => {
    const ghost = document.getElementById('ghost');
    event.dataTransfer.effectAllowed = 'copy';
    event.dataTransfer.setDragImage(ghost, 0, 0);
    event.dataTransfer.setData('text', 'text');
  }, []);

  const [text, setText] = useState('');
  const [dragText, setDragText] = useState('');

  const renderItemToDrag = useCallback(
    (text: string) => {
      return (
        <>
          <div
            id='drag-zone'
            draggable
            onDragStart={handleOnDrag}
            style={{
              border: '1px solid black',
              padding: '10px',
              width: '50%',
              marginBottom: '10px',
            }}
          >
            <span>{text}</span>
          </div>
          <div
            id='ghost'
            style={{
              position: 'absolute',
              top: '-1000px',
              width: '100px',
              height: '30px',
              display: 'flex',
              justifyContent: 'center',
              alignItems: 'center',
              textAlign: 'center',
            }}
          >
            Copy to {dragText}
          </div>
        </>
      );
    },
    [dragText]
  );

  return (
    <>
      {renderItemToDrag('this is a draggable')}

      <div
        id='drop-zone'
        onDrop={(e) => {
          const data = e.dataTransfer.getData('text');
          setText(data);
        }}
        onDragOver={(e) => {
          e.dataTransfer.dropEffect = 'none';
          if ((e.target as HTMLElement).className === 'infomation') {
            e.dataTransfer.dropEffect = 'copy';
            setDragText('infomation');
          }
          e.preventDefault();
        }}
        style={{
          display: 'flex',
          flexDirection: 'column',
          gap: '10px',
          width: '400px',
        }}
      >
        <h3 className='infomation'>Drop area</h3>
        <span
          style={{ border: '1px solid black', padding: '10px', width: '200px' }}
        >
          {text}
        </span>
      </div>
    </>
  );
};

Expected behavior:

Current behavior:

I've tried:

Is it possible to update a drag ghost image's content during a drag operation? If so, how can I achieve this?

Upvotes: -1

Views: 71

Answers (1)

chrwahl
chrwahl

Reputation: 13145

It is not possible to change the drag image after it has been set in the dragstart callback function.

This method [setDragImage()] must be called in the dragstart event handler.

DataTransfer: setDragImage() method

And updating the source of the image will not generate a new one.

Upvotes: 0

Related Questions