Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot call beginDrag while dragging #545

Closed
vugman opened this issue Sep 22, 2016 · 14 comments · Fixed by #820
Closed

Cannot call beginDrag while dragging #545

vugman opened this issue Sep 22, 2016 · 14 comments · Fixed by #820

Comments

@vugman
Copy link

vugman commented Sep 22, 2016

Hi,

I have a nested component inside a DropTarget which has items that can also be dragged (not using react-dnd). the issue is that once i drag an item i get this error.

Is there a way to disable it? or override it?

Thanks!

@BabanovRoman
Copy link

BabanovRoman commented Sep 26, 2016

It's my code and i have two errors -

1) Cannot call beginDrag while dragging

2) Cannot call hover after drop.

What can i do to fixed id? Help help help pls!!!
`'use strict';

import React, { PropTypes } from 'react';
import ReactDOM from 'react-dom';
import { DragSource, DropTarget } from 'react-dnd';

import View from '../View';
import Text from '../Text.jsx';
import TableItemSelect from './TableItemSelect.jsx';
import { Option } from '../Select';
import FontIcon from '../FontIcon.jsx';
import CloseCross from '../CloseCross';

import { StyleSheet, css } from '@roistat/ui';
import { COLOR, FONT } from '../../const/theme.js';

const ItemTypes = {
ColumnSettingsTableItem: 'columnSettingsTableItem'
};

const itemSource = {
beginDrag(props) {
return { index: props.index };
}
};

const itemTarget = {
hover(props, monitor, component) {
const dragIndex = monitor.getItem().index;
const hoverIndex = props.index;

    if (dragIndex === hoverIndex) {
        return;
    }

    const hoverBoundingRect = ReactDOM.findDOMNode(component).getBoundingClientRect();
    const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
    const clientOffset = monitor.getClientOffset();
    const hoverClientY = clientOffset.y - hoverBoundingRect.top;

    if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
        return;
    }

    if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
        return;
    }

    props.moveItem(dragIndex, hoverIndex);

    monitor.getItem().index = hoverIndex;
}

};

@DropTarget(ItemTypes.ColumnSettingsTableItem, itemTarget, connect => ({
connectDropTarget: connect.dropTarget()
}))
@DragSource(ItemTypes.ColumnSettingsTableItem, itemSource, (connect, monitor) => ({
connectDragSource: connect.dragSource(),
connectDragPreview: connect.dragPreview(),
isDragging: monitor.isDragging()
}))
export default class ColumnSettingsTableItem extends React.Component {
static propTypes = {
connectDragSource: PropTypes.func.isRequired,
connectDropTarget: PropTypes.func.isRequired,
isDragging: PropTypes.bool.isRequired,
moveItem: PropTypes.func.isRequired,
index: PropTypes.number,
number: PropTypes.number,
onRemove: PropTypes.func,
onSelectType: PropTypes.func,
typeOptions: PropTypes.arrayOf(PropTypes.shape({
title: PropTypes.string,
value: PropTypes.string
})),
isFirstItem: PropTypes.bool,
typePlaceholder: PropTypes.string
};

_renderSelectOptions() {
    const props = this.props;
    const options = props.typeOptions;

    return options.map(option => (
        <Option key={`tableItem_${option.value}`} value={option.value}>
            {option.title}
        </Option>
    ));
}

_onSelectHandler(option) {
    const props = this.props;

    props.onSelectType && props.onSelectType(option)
}

_onRemoveHandler() {
    const props = this.props;

    props.onRemove && props.onRemove();
}

render() {
    const props = this.props;
    const isFirstItem = props.isFirstItem;
    const isHasOptions = !!props.typeOptions;
    const number = props.number;
    const isHasNumber = number !== null;

    const { connectDragSource, connectDropTarget, connectDragPreview } = this.props;

    return connectDragPreview(connectDropTarget(
        <div>
            <View styles={[styles.item]}>
                <View styles={[isHasNumber ? styles.columnIdx : styles.emptyIndex]}>
                    <Text styles={[styles.idxText]}>
                        {isHasNumber && number}
                    </Text>
                </View>
                <View styles={[styles.panel, styles.item, isFirstItem && styles.firstItem]}>
                    <View styles={[styles.leftItem, styles.item]}>
                        {
                            connectDragSource(
                                <div>
                                    <View>
                                        <FontIcon
                                            name="bars"
                                            styles={[styles.barsIcon]}
                                        />
                                    </View>
                                </div>
                            )
                        }
                        <Text
                            styles={[styles.textView]}
                            numberOfLines={1}
                            title={props.children}
                        >
                            {props.children}
                        </Text>
                    </View>
                    {
                        isHasOptions &&
                            <View styles={[styles.rightItem, styles.item]}>
                                <TableItemSelect
                                    placeholder={props.typePlaceholder}
                                    onChange={this._onSelectHandler.bind(this)}
                                >
                                    {this._renderSelectOptions()}
                                </TableItemSelect>
                            </View>
                    }
                </View>
                <View
                    styles={[styles.removeIconView]}
                    onClick={this._onRemoveHandler.bind(this)}
                >
                <View>
                    <CloseCross color={COLOR.PRIMARY_MEDIUM}/>
                </View>
                </View>
            </View>
        </div>
    ))
}

}

const styles = StyleSheet.create({
panel: {
height: '1.5rem',
overflow: 'hidden',
borderRadius: '2px',
border: '1px solid rgb(232, 233, 234)',
borderTop: 'none',
backgroundColor: '#ffffff'
},
firstItem: {
borderTop: '1px solid rgb(232, 233, 234)'
},
leftItem: {
alignItems: 'center',
paddingLeft: '.5rem',
overflow: 'hidden'
},
rightItem: {
'&:hover': {
backgroundColor: COLOR.GRAY_HOVER
},
backgroundColor: '#ffffff',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'stretch',
paddingLeft: '.5rem',
borderLeft: '1px solid rgb(232, 233, 234)'
},
item: {
flex:1
},
columnIdx: {
alignItems: 'center',
padding: '0 .5rem'
},
emptyIndex: {
alignItems: 'center',
padding: '0 .7rem'
},
idxText: {
color: COLOR.MUTED
},
barsIcon: {
color: '#d7d8d9',
cursor: 'move',
fontSize: FONT.SIZE_TEXT
},
removeIconView: {
alignItems: 'center',
padding: '0 .5rem'
},
removeIcon: {
color: COLOR.PRIMARY_MEDIUM,
fontSize: FONT.SIZE_BUTTON,
cursor: 'pointer'
},
textView: {
marginLeft: '.5rem',
alignItems: 'center'
}
});`

@mikhail-eremin
Copy link

mikhail-eremin commented Oct 13, 2016

I have the same problem. Using react-dnd 2.1.4 with react-virtualized endless scroll. When scrolling while dragging item (e.g. we want to put dragged element to some droppable at the bottom of the scrolling list) - drag source element is unmounted after some scrolling, but nothing goes wrong at this point - drop event successfully captured, everything looks okay. But when we try to drag next item after that - react-dnd says "Cannot call beginDrag while dragging."
Can't find any working way to avoid this, please suggest.
Is there any simple way to tell react-dnd that we finished dragging? Is it about END_DRAG action? How do I dispatch it manually? I read some similar issues here but have no luck finding any complete solution.
P.S. Thanks for your work! 👍

@m0xx
Copy link

m0xx commented Jan 11, 2017

@mikhail-eremin I have the same problem... Did you find any workaround by any chance? thanks

@mikhail-eremin
Copy link

mikhail-eremin commented Jan 12, 2017

@m0xx I did weird workaround for it - in my case problem occurs because drag source element is being unmounted while we drag it (I use react-virtualized and if you scroll for a while while dragging - some items from the top can be unmounted - this is how react-virtualized works)
So, as drag source element was unmounted - no END_DRAG action happens and react-dnd thinks that drag is still in progress

So what I do is remembering the fact that certain item (current drag source) was unmounted (use componentWillUnmount in dragged item) and when in DROP source monitor (in my case) I check if some source was unmounted during drag, and if so - I manually dispatch action:
monitor.internalMonitor.store.dispatch({type: "dnd-core/END_DRAG"}) (react-dnd works with redux inside, I found this action looking throught react-dnd sources).

This small trick helps in my case, but still, it is kinda dirty hack.

@m0xx
Copy link

m0xx commented Jan 16, 2017

@mikhail-eremin Thanks for the workaround, I use react-virtualized too so I had the same problem!

@bebbi
Copy link

bebbi commented Feb 23, 2017

I have this issue very randomly. I can't reproduce yet. Not a problem with keys (they are hashed by content) or disappearing dom elements.
Related: #442.

I think the referenced PR makes sense, can you include that fix here too?

@ms88privat
Copy link
Contributor

@darthtrevino We run into the same issue today. The linked PR (https://github.com/Asana/react-dnd-html5-backend/pull/6/files) does fix the problem. Can it be included here please?

@liorbrauer
Copy link

@darthtrevino Hi, we've tried installing version 2.5.0 but it seems npm wasn't updated and the latest release is still 2.4.0?

@darthtrevino
Copy link
Member

@liorbrauer, the html5 backend is set at 2.5.0, but the other packages are at 2.4.0 presently. We're using Lerna to manage versioning, and it looks like it won't release packages that have not been updated (https://github.com/lerna/lerna#fixedlocked-mode-default). If this is causing issues, let me know.

@liorbrauer
Copy link

liorbrauer commented Aug 28, 2017

@darthtrevino thanks for the reply! I guess I'm a bit confused on how to get the latest html5 backend. We currently have both react-dnd and react-dnd-html5-backend packages (version 2.4.0 and 2.4.1 respectively) in our package.json. How do I install and import react-dnd-html5-backend from the monorepo instead?

@liorbrauer
Copy link

@darthtrevino Hi again, sorry for nagging but I still cannot find how to use the latest version of html5 backend (2.5.0).

The latest version listed under NPM (https://www.npmjs.com/package/react-dnd-html5-backend) is still 2.4.1.

Maybe I'm missing something?

@ms88privat
Copy link
Contributor

We are having the same problem. For now we do self host the html5 backend package.

@liorbrauer
Copy link

@ms88privat thanks for the reply. FWIW, isn't this just a matter of updating the NPM package(s)?

@darthtrevino
Copy link
Member

darthtrevino commented Sep 5, 2017 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants