question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Wrong dragPreview in Chrome

See original GitHub issue

Describe the bug I see two different dragPreview for the same code. I find that results are fine as expected but on Chrome I see two issues:

  1. dragPreview height is not right.
  2. I am seeing a white color in the background.

Google Chrome d2GjfYizYL

Firefox j1fxz8Yywn

Code samples:

File 1

import React from 'react';
import {__} from '@wordpress/i18n';
import {DndProvider} from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
import update from 'immutability-helper';
import Legend from '../Legend/Legend';
import Header from './Header';
import RowWithDragHandle from './RowWithDragHandle';
import AddRowButton from './AddRowButton';

function uniqid() {
    // Math.random should be unique because of its seeding algorithm.
    // Convert it to base 36 (numbers + letters), and grab the first 9 characters
    // after the decimal.
    return `_${Math.random()
        .toString(36)
        .substr(2, 9)}`;
}

export default function DonationAmounts() {
    const [row, setRow] = React.useState([{id: uniqid()}]);

    const handleAddRow = () => {
        setRow([...row, {id: uniqid()}]);
    };

    const handleDeleteRow = rowID => {
        const temp = row.filter(item => rowID !== item.id);
        setRow(temp);
    };

    const moveCard = React.useCallback(
        (dragIndex, hoverIndex) => {
            const dragRow = row[dragIndex];
            setRow(
                update(row, {
                    $splice: [[dragIndex, 1], [hoverIndex, 0, dragRow]],
                })
            );
        },
        [row]
    );

    return (
        <div className="text-xs">
            <fieldset>
                <Legend instructions={__('You can create list of amounts for donation', 'givewp-campaigns')}>
                    {__('Amounts', 'givewp-campaigns')}
                </Legend>
                <div className="mb-7 rounded border border-campaign-white-300 overflow-hidden">
                    <Header />
                    <div className="px-3 pt-3 text-campaign-gray-600">
                        <DndProvider backend={HTML5Backend}>
                            {row.map(({id}, index) => (
                                <RowWithDragHandle
                                    key={id}
                                    id={id}
                                    index={index}
                                    onDeleteRow={handleDeleteRow}
                                    showCloseButton={row.length > 1}
                                    moveCard={moveCard}
                                />
                            ))}
                        </DndProvider>
                    </div>
                </div>
            </fieldset>
            <AddRowButton onAddRow={handleAddRow} />
        </div>
    );
}

File 2

import React from 'react';
import {__} from '@wordpress/i18n';
import PropTypes from 'prop-types';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
import {faArrowsAlt, faDollarSign} from '@fortawesome/free-solid-svg-icons';
import {useDrag, useDrop} from 'react-dnd';
import CloseButton from './CloseButton';
import NumberInput from '../NumberInput/NumberInput';
import TextInput from '../TextInput/TextInput';

const RowWithDragHandle = ({id, index, onDeleteRow, showCloseButton, moveCard}) => {
    const ref = React.useRef(null);
    const [, drop] = useDrop({
        accept: 'card',
        hover(item, monitor) {
            if (!ref.current) {
                return;
            }
            const dragIndex = item.index;
            const hoverIndex = index;
            // Don't replace items with themselves
            if (dragIndex === hoverIndex) {
                return;
            }
            // Determine rectangle on screen
            const hoverBoundingRect = ref.current.getBoundingClientRect();
            // Get vertical middle
            const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
            // Determine mouse position
            const clientOffset = monitor.getClientOffset();
            // Get pixels to the top
            const hoverClientY = clientOffset.y - hoverBoundingRect.top;
            // Only perform the move when the mouse has crossed half of the items height
            // When dragging downwards, only move when the cursor is below 50%
            // When dragging upwards, only move when the cursor is above 50%
            // Dragging downwards
            if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
                return;
            }
            // Dragging upwards
            if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
                return;
            }
            // Time to actually perform the action
            moveCard(dragIndex, hoverIndex);
            // Note: we're mutating the monitor item here!
            // Generally it's better to avoid mutations,
            // but it's good here for the sake of performance
            // to avoid expensive index searches.
            // eslint-disable-next-line no-param-reassign
            item.index = hoverIndex;
        },
    });

    const [{isDragging}, drag] = useDrag({
        item: {type: 'card', id, index},
        collect: monitor => ({
            isDragging: monitor.isDragging(),
        }),
    });

    const opacity = isDragging ? 0 : 1;

    drag(drop(ref));

    return (
        <div className="mb-3 flex items-center" style={{opacity}} ref={ref}>
            <div className="pr-3">
                <NumberInput
                    name="donationAmounts[][amount]"
                    label={__('Amount', 'givewp-campaigns')}
                    labelHidden
                    min={0}
                    value={10}
                    prefix={<FontAwesomeIcon icon={faDollarSign} />}
                    onChange={() => {}}
                    className="pl-1 pr-1 leading-tight"
                    style={{maxWidth: '55px'}}
                />
            </div>
            <div className="pr-3">
                <TextInput
                    name="donationAmounts[][text]"
                    label={__('Text', 'givewp-campaigns')}
                    labelHidden
                    min={0}
                    value="demo text"
                    onChange={() => {}}
                    className="leading-tight"
                />
            </div>
            <div className="cursor-move pr-3">
                <FontAwesomeIcon icon={faArrowsAlt} className="text-gray-400" />
            </div>
            {showCloseButton && <CloseButton onClick={() => onDeleteRow(id)} />}
        </div>
    );
};

RowWithDragHandle.propTypes = {
    id: PropTypes.string.isRequired,
    index: PropTypes.number.isRequired,
    onDeleteRow: PropTypes.func.isRequired,
    showCloseButton: PropTypes.bool.isRequired,
    moveCard: PropTypes.func.isRequired,
};

export default RowWithDragHandle;

Expected Behavior I expect the same behavior on Firefox and Google Chrome when drag row.

  • OS: IOS
  • Browser Google Chrome 78
"react-dnd": "^9.4.0",
"react-dnd-html5-backend": "^9.4.0",

Related I did not see any positive response on the closed issue that’s why I am creating a new issue. ref: https://github.com/react-dnd/react-dnd/issues/832

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:1
  • Comments:10

github_iconTop GitHub Comments

9reactions
yume-chancommented, Jan 13, 2020

The white background is added by Chrome, maybe to optimize performance (get the preview image from composited graphic buffer?).

I learned from SortableJS that adding a transform: translateZ(0) to the drag source can workaround this problem. Maybe because Chrome now creates an extra layer for your element.

3reactions
joshuahigginscommented, Jun 5, 2020

The child element size issue is what I’m experiencing. In my case, the child element is a scrollable container. The preview is applied inconsistently. Sometimes it drags just the displayed element, sometimes it drags the displayed and the next element, and sometimes it drags just the displayed element, but it offsets the height by the overflow size of the child (ignoring the true child element size). This is the same code and no change… It’s just kind of random which happens.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Wrong dragPreview in Chrome · Issue #832 · react-dnd/react ...
In my case draggable table row node is both source and target. For some reasons drag preview contains not only source node screenshot,...
Read more >
drag and drop not working in latest version of chrome
I have faced the drag and drop related issue in latest version of chrome browser. Since we have used the draggable element in...
Read more >
Drag-preview is positioned wrong when using translate3d on ...
If i make an element draggable, and use translate3d on any child element, the drag preview of the browser is gonna positioned wrong....
Read more >
Chrome: Inspect elements that appear only when dragging
Open chrome devtools; Click on the Sources tab; Go to Event Listeners Breakpoints down there; Om the event list, click Drag / drop,...
Read more >
Can't drag Google Chrome tabs on your PC? Here are some ...
Some workarounds to try · 1. Restore settings to default: The first thing you may try is resetting Chrome. · 2. Check your...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found