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

Warning With Nested DragSource #431

Closed
jchristman opened this issue Apr 6, 2016 · 27 comments
Closed

Warning With Nested DragSource #431

jchristman opened this issue Apr 6, 2016 · 27 comments

Comments

@jchristman
Copy link

If you have a DragSource inside of a component that is also a DragSource (i.e. drag something within a draggable), whenever the parent component is dragged, the following warning appears.

Warning: setState(...): Cannot update during an existing state transition (such as within `render`). Render methods should be a pure function of props and state.
warning @   modules.js?hash=107dc56…:19491
getInternalInstanceReadyForUpdate   @   modules.js?hash=107dc56…:5476
ReactUpdateQueue.enqueueSetState    @   modules.js?hash=107dc56…:5617
ReactComponent.setState @   modules.js?hash=107dc56…:15132
handleChange    @   modules.js?hash=107dc56…:20844
handleChange    @   modules.js?hash=107dc56…:22861
dispatch    @   modules.js?hash=107dc56…:23568
addSource   @   modules.js?hash=107dc56…:23124
registerSource  @   modules.js?hash=107dc56…:21172
receiveType @   modules.js?hash=107dc56…:21099
receiveProps    @   modules.js?hash=107dc56…:21089
DragSource(NestedComponent) @   modules.js?hash=107dc56…:21062
ReactCompositeComponentMixin.mountComponent @   modules.js?hash=107dc56…:6679
ReactCompositeComponent_mountComponent  @   modules.js?hash=107dc56…:896
ReactReconciler.mountComponent  @   modules.js?hash=107dc56…:5167
ReactMultiChild.Mixin.mountChildren @   modules.js?hash=107dc56…:13562
ReactDOMComponent.Mixin._createContentMarkup    @   modules.js?hash=107dc56…:10901
ReactDOMComponent.Mixin.mountComponent  @   modules.js?hash=107dc56…:10789
ReactReconciler.mountComponent  @   modules.js?hash=107dc56…:5167
ReactCompositeComponentMixin._updateRenderedComponent   @   modules.js?hash=107dc56…:7101
ReactCompositeComponentMixin._performComponentUpdate    @   modules.js?hash=107dc56…:7075
ReactCompositeComponentMixin.updateComponent    @   modules.js?hash=107dc56…:7004
ReactCompositeComponent_updateComponent @   modules.js?hash=107dc56…:896
ReactCompositeComponentMixin.receiveComponent   @   modules.js?hash=107dc56…:6936
ReactReconciler.receiveComponent    @   modules.js?hash=107dc56…:5217
ReactCompositeComponentMixin._updateRenderedComponent   @   modules.js?hash=107dc56…:7093
ReactCompositeComponentMixin._performComponentUpdate    @   modules.js?hash=107dc56…:7075
ReactCompositeComponentMixin.updateComponent    @   modules.js?hash=107dc56…:7004
ReactCompositeComponent_updateComponent @   modules.js?hash=107dc56…:896
ReactCompositeComponentMixin.receiveComponent   @   modules.js?hash=107dc56…:6936
ReactReconciler.receiveComponent    @   modules.js?hash=107dc56…:5217
ReactCompositeComponentMixin._updateRenderedComponent   @   modules.js?hash=107dc56…:7093
ReactCompositeComponentMixin._performComponentUpdate    @   modules.js?hash=107dc56…:7075
ReactCompositeComponentMixin.updateComponent    @   modules.js?hash=107dc56…:7004
ReactCompositeComponent_updateComponent @   modules.js?hash=107dc56…:896
ReactCompositeComponentMixin.performUpdateIfNecessary   @   modules.js?hash=107dc56…:6952
ReactReconciler.performUpdateIfNecessary    @   modules.js?hash=107dc56…:5232
runBatchedUpdates   @   modules.js?hash=107dc56…:5832
Mixin.perform   @   modules.js?hash=107dc56…:6304
Mixin.perform   @   modules.js?hash=107dc56…:6304
assign.perform  @   modules.js?hash=107dc56…:5789
flushBatchedUpdates @   modules.js?hash=107dc56…:5850
ReactUpdates_flushBatchedUpdates    @   modules.js?hash=107dc56…:896
Mixin.closeAll  @   modules.js?hash=107dc56…:6370
Mixin.perform   @   modules.js?hash=107dc56…:6317
ReactDefaultBatchingStrategy.batchedUpdates @   modules.js?hash=107dc56…:10295
enqueueUpdate   @   modules.js?hash=107dc56…:5879
enqueueUpdate   @   modules.js?hash=107dc56…:5460
ReactUpdateQueue.enqueueSetState    @   modules.js?hash=107dc56…:5626
ReactComponent.setState @   modules.js?hash=107dc56…:15132
handleChange    @   modules.js?hash=107dc56…:21121
handleChange    @   modules.js?hash=107dc56…:22861
dispatch    @   modules.js?hash=107dc56…:23568
(anonymous function)    @   modules.js?hash=107dc56…:22100
endDragIfSourceWasRemovedFromDOM    @   modules.js?hash=107dc56…:29563
handleTopDrop   @   modules.js?hash=107dc56…:29860

An example of this would be:

class ParentDraggable extends React.Component {
    render() {
        return this.props.connectDragSource(
            <NestedDraggable/>
        );
    }
}

//... Skip the code for containers

class NestedDraggable extends React.Component {
    render() {
        return this.props.connectDragSource(
            <div></div>
        );
    }
}

I believe the issue stems from the fact that rerendering the parent component causes the child DragSource call to make a call to setState during receiveProps function call?

@nihtalak
Copy link

nihtalak commented Apr 7, 2016

👍

@gaearon
Copy link
Member

gaearon commented Apr 9, 2016

Can you please provide a project reproducing the problem?

@jchristman
Copy link
Author

I'm trying to produce an simple example and am having problems reproducing outside of my private project that I'm working on. @nihtalak , do you have a repo on Github that produces the issue?

@ebakan
Copy link

ebakan commented Apr 10, 2016

Here's a tiny repo exhibiting the described behavior: https://github.com/ebakan/react-dnd-nested-bug

@ebakan
Copy link

ebakan commented Apr 10, 2016

Curiously, the Component only throws this error when it's listening for monitor.getItem(). If it's listening for monitor.isDragging() it'll work properly, as shown in this branch: https://github.com/ebakan/react-dnd-nested-bug/tree/no-error-with-is-dragging

@ebakan
Copy link

ebakan commented Apr 10, 2016

It will also throw the error when listening to monitor.getItemType(): https://github.com/ebakan/react-dnd-nested-bug/tree/error-with-get-item-type

@jchristman
Copy link
Author

@ebakan - interesting. I'm wondering what's causing this bug to appear in my code, which does use isDragging. I am doing some wonky things with the nested draggable, so it could be a manifestation of the same bug you are seeing. Thanks for the help reproducing!

@hakunin
Copy link

hakunin commented Apr 11, 2016

I have nested draggables too, but not sure if thats the issue.
It seems to be creating a new store and the code thats listening to. I made a video if that helps:
http://screencast.com/t/qCrJRPAS2MYR

Update: found the issue, I had a leftover listener so in my case it wasn't due to react-dnd.
Update2: I spoke too soon. Upon removing the leftover listener, I still get the warning.

@hakunin
Copy link

hakunin commented May 23, 2016

I just added Dnd to another component and noticed this issue even without nested or multiple dragging components.

After a bit of digging I found that the issue is connected to custom drag layer rendering the component while being dragged.

If I put text instead the component being dragged it works fine. The component itself is the drag source.

@brianreavis
Copy link

@jchristman @hakunin I don't have nested draggables, but encountered Cannot update during an existing state transition when I had a drop target conditionally rendered based on isDragging. Could this be the case in any of your examples? Something sort of like this:

render() {
    var dropZone;
    if (this.props.isDragging) dropZone = <MyDropTarget />;
    return <div>
       <MyDragSource />
       {dropZone}
    </div>
}

Ended up working around it by using display: none/block to hide the target instead of adding and removing the component when dragging is active.

@jchristman
Copy link
Author

I think that could be the issue. I will check and let you know. That's is definitely the construct I'm using right now.

@jchristman
Copy link
Author

Naw - I'm getting the issue when the "drop" happens. Then it tries to rerender the component and throws this warning.

@arjunu
Copy link

arjunu commented Jul 28, 2016

Got same warning when my drag preview was a component which was a DragSource (which I'm not supposed to do).

@gharwood1
Copy link

@jchristman did you ever come up with a solution for this?

Im working with nested dragSources and suddenly started seeing this error when dropping the nested resource.

I can provide an example but wanted to see if anyone had solved the issue, or had a suitable workaround.

@hakunin
Copy link

hakunin commented Aug 16, 2016

Got same warning when my drag preview was a component which was a DragSource (which I'm not supposed to do).

Thanks @arjunu my warning was caused by this!
I still do have these occasionally so I guess some other reason is there to be fixed as well. Might be on my part :)

@kesne kesne added the triage label Aug 20, 2016
@jchristman
Copy link
Author

@gharwood1, I'm just livin with the issue until it can be fixed. I spent a few hours once trying to really understand this library so I could pull request a fix but it's pretty complex, so I moved on. I just don't have the time... :-(

@arackaf
Copy link

arackaf commented Nov 22, 2016

@gaearon I don't quite have a project made that's capable of someone pulling down, but I think I can get one made if needed.

Basically, is what I'm trying to do here valid:

https://github.com/arackaf/booklist/blob/react-dnd-bug-freeze/react-redux/modules/subjects/components/subjectsList-es6.js

If I disable the conditional in line 64 everything's fine

if (this.props.draggingSubject){
    effectiveChildren.push(this.props.draggingSubject);
}

but the minute the results of the drag event starts modifying props and rendering of components, the warning above starts getting spit out frequently.

Should I not be doing this?

The use case is basically to "preview" the currently dragged item in the drop target. The above is a proof of concept - not wired into the Redux store yet, since I'm not sure if this is even valid.


Hm, looks like it's fine if I keep my changes local to SubjectDisplayContent, but the warnings start happening if the changes extend to SubjectDisplay. So basically, if a dropTarget sends props down that modify a different dropTarget, react-dnd gets annoyed. Is this expected, and I need to re-think some things, or is this a bug with dnd?

@Robinfr
Copy link

Robinfr commented Feb 9, 2017

I'm experiencing exactly the same problem. What you can do in some situations is create a DragDropContext around each nested draggable. But this doesn't work as soon as you want a custom DragLayer..

@jchenjc
Copy link

jchenjc commented Feb 12, 2017

I got the same error, except I am doing a nested dropTargets.
After looking around in the documentation, I tried using

isOver(options): Returns true if there is a drag operation is in progress, and the pointer is currently hovering over the owner. You may optionally pass { shallow: true } to strictly check whether only the owner is being hovered, as opposed to a nested target.

(with the shallow is true option) in the canDrop function of the parent dropTarget, and the issue went away. I would think the same could be applied to some other scenarios.

@Robinfr
Copy link

Robinfr commented Feb 13, 2017

@jchenjc I tried this but it didn't work for me. To be honest my situation is extremely complicated with nested drag preview + drag source + drop target that needs to work across lists.

@AndrewSouthpaw
Copy link

FWIW: I have both nested drag sources and a custom drag layer. When I remove the custom drag layer, the message goes away. From inspecting the stack trace, it looks like the problem is here:

printWarning	@	warning.js?8a56:36
warning	@	warning.js?8a56:60
getInternalInstanceReadyForUpdate	@	ReactUpdateQueue.js?6531:54
enqueueSetState	@	ReactUpdateQueue.js?6531:200
ReactComponent.setState	@	ReactComponent.js?702a:63
handleChange	@	DragLayer.js?1cbc:124 <--------------
handleChange	@	DragDropMonitor.js?0588:60

Relevant code is here. I'm going to look into why the state might be different in my case to trigger a re-render...

@nottoseethesun
Copy link

With a dragsource+droptarget nested inside a droptarget, I get this issue.

@jedwards1211
Copy link
Contributor

Part of the reason this happened is because gaearon envisoned doing list drag and drop by making every list item a drop target, rather than making the list component a single drop target that determines what to do based upon the drag hover position. The latter way is how most other DnD systems I've seen do things.

@davidjoy
Copy link

Just in case it helps someone: I encountered this when I was rendering a component that was a drag source in my custom drag layer because it was convenient. I used the drag source component because it was the same entity that I was trying to drag, so it just made sense to me to keep the code "DRY" by reusing it. I didn't think about the fact that it had all the dragSource code in it - looking back, of course I wouldn't want a drag source AS the thing to render in the custom drag layer.

I ultimately split up my component into a "Draggable" version that wrapped the base component, and then used the base component in my custom drag layer. No more warning, better code! 👍

@hakunin
Copy link

hakunin commented Jul 24, 2017

@davidjoy woah, thanks for sharing! I am doing the same thing, need to try it as well!

@hakunin
Copy link

hakunin commented Jul 28, 2017

@davidjoy Just fixed mine as well. Your suggestion points to not using DragSource and such for the custom layer. What I did was simply to use the naked component without DragSource in my custom drag layer and that did the trick.

@stale
Copy link

stale bot commented Jul 6, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Jul 6, 2019
@stale stale bot closed this as completed Jul 13, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests