React-dnd: 嵌套DragSource警告

创建于 2016-04-06  ·  27评论  ·  资料来源: react-dnd/react-dnd

如果在组件内也有DragSource,而该组件又是DragSource(即在可拖动对象内拖动某些东西),则只要拖动父组件,就会出现以下警告。

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

例如:

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>
        );
    }
}

我认为问题源于以下事实:重新呈现父组件会导致子DragSource调用在receiveProps函数调用期间对setState进行调用?

triage wontfix

最有用的评论

以防万一它对某人有帮助:我在自定义拖动层中渲染作为拖动源的组件时遇到了这个问题,因为它很方便。 我使用了拖动源组件,因为它与我尝试拖动的实体相同,所以对我来说,通过重用它来保持代码“ DRY”就很有意义。 我没有考虑过其中包含所有dragSource代码的事实-回头看,当然,我不希望将拖动源作为事物呈现在自定义拖动层中。

最终,我将组件拆分为一个“可拖动”版本,该版本包装了基本组件,然后在自定义拖动层中使用了基本组件。 没有更多的警告,更好的代码! 👍

所有27条评论

:+1:

您能提供一个再现问题的项目吗?

我试图给出一个简单的示例,但是在我正在从事的私人项目之外重现问题。 @nihtalak ,您是否在产生问题的Github上有一个回购协议?

这是一个展示所描述行为的小型仓库: https :

奇怪的是, Component仅在侦听monitor.getItem()时抛出此错误。 如果它正在监听monitor.isDragging()它将正常工作,如该分支所示: https :

收听monitor.getItemType()时也会抛出错误: https :

@ebakan-有趣。 我想知道是什么导致此错误出现在我的代码中,该代码确实使用了isDragging。 我正在使用可拖动的嵌套做一些奇怪的事情,因此它可能是您所看到的同一错误的体现。 感谢您的帮助复制!

我也嵌套了可拖动对象,但是不确定这是否是问题。
似乎正在创建一个新商店以及正在侦听的代码。 我制作了一个视频,如果有帮助的话:
http://screencast.com/t/qCrJRPAS2MYR

更新:发现了问题,我有一个剩余的侦听器,因此在我看来,这不是由于react-dnd引起的。
Update2:我讲得太早了。 删除剩余的侦听器后,我仍然会收到警告。

我只是将Dnd添加到另一个组件中,即使没有嵌套或多个拖动组件,也注意到了此问题。

经过一番挖掘后,我发现问题与自定义拖动层有关,而该拖动层在拖动时渲染了组件。

如果我改用文字,则拖动的组件效果很好。 组件本身就是拖动源。

@jchristman @hakunin我没有嵌套的可拖动对象,但是当我基于isDragging有条件地渲染放置目标时遇到了Cannot update during an existing state transition isDragging 。 您的任何示例都可能是这种情况吗? 像这样的东西:

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

最终通过使用display: none/block隐藏目标来解决此问题,而不是在活动拖动时添加和删除组件。

我认为这可能是问题。 我会检查并告知您。 那绝对是我现在正在使用的构造。

w-当“掉落”发生时,我遇到了问题。 然后,它尝试重新呈现该组件并引发此警告。

当我的拖动预览是一个DragSource组件时,我得到了同样的警告(我不应该这样做)。

@jchristman您是否曾经

我正在使用嵌套的dragSources,在删除嵌套的资源时突然开始看到此错误。

我可以提供一个示例,但想看看是否有人解决了该问题,或者有合适的解决方法。

当我的拖动预览是一个DragSource组件时,我得到了同样的警告(我不应该这样做)。

谢谢@arjunu,我的警告是由此引起的!
我偶尔还是有这些,所以我想还有其他一些原因也要解决。 可能是我的一部分:)

@ gharwood1 ,在解决该问题之前,我还是很满意。 我花了几个小时试图真正理解这个库,所以我可以请求修复,但是它很复杂,所以我继续前进。 我只是没有时间... :-(

@gaearon我还没有一个能够使某人失望的项目,但是我认为如果需要的话我可以做出一个。

基本上,这就是我要在此处尝试执行的操作:

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

如果我在第64行中禁用条件,一切都很好

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

但是拖动事件的结果开始修改道具和渲染组件的那一刻,上面的警告开始频繁吐出。

我不应该这样做吗?

用例基本上是“预览”放置目标中当前拖动的项目。 以上是概念证明-尚未连接到Redux商店,因为我不确定这是否有效。


嗯,如果我将更改保留在本地SubjectDisplayContent看起来很好,但是如果更改扩展到SubjectDisplay ,就会开始出现警告。 因此,基本上,如果dropTarget向下发送用于修改其他dropTarget的道具,则react-dnd会很烦。 这是预期的,我需要重新考虑一些事情,或者这是dnd的错误?

我遇到了完全相同的问题。 在某些情况下,您可以做的是在每个嵌套的可拖动对象周围创建一个DragDropContext 。 但这在您需要自定义DragLayer时不起作用。

除了执行嵌套的dropTargets之外,我遇到了相同的错误。
浏览文档后,我尝试使用

isOver(options):如果正在进行拖动操作,并且指针当前悬停在所有者上,则返回true。 您可以选择传递{shallow:true}来严格检查是否只徘徊了所有者,而不是嵌套目标。

(在父级dropTarget的canDrop函数中使用“ shallow是true”选项),问题就消失了。 我认为同样可以应用于其他一些情况。

@jchenjc我试过了,但是对我

FWIW:我同时嵌套了拖动源和自定义拖动层。 当我删除自定义拖动层时,消息消失了。 通过检查堆栈跟踪,看起来问题出在这里:

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

相关代码在这里。 我将研究为什么在我的情况下状态可能会有所不同以触发重新渲染...

通过在droptarget内嵌套的dragsource + droptarget,我遇到了这个问题。

发生这种情况的部分原因是因为gaearon设想通过将每个列表项作为放置目标来进行列表拖放,而不是使列表组件成为根据拖动悬停位置来确定要执行的操作的单个放置目标。 后一种方式是我见过的大多数其他DnD系统的工作方式。

以防万一它对某人有帮助:我在自定义拖动层中渲染作为拖动源的组件时遇到了这个问题,因为它很方便。 我使用了拖动源组件,因为它与我尝试拖动的实体相同,所以对我来说,通过重用它来保持代码“ DRY”就很有意义。 我没有考虑过其中包含所有dragSource代码的事实-回头看,当然,我不希望将拖动源作为事物呈现在自定义拖动层中。

最终,我将组件拆分为一个“可拖动”版本,该版本包装了基本组件,然后在自定义拖动层中使用了基本组件。 没有更多的警告,更好的代码! 👍

@davidjoy哇,谢谢分享! 我在做同样的事情,也需要尝试一下!

@davidjoy也可以固定我的。 您的建议是针对自定义图层不使用DragSource等。 我所做的只是在我的自定义拖动层中使用没有DragSource的裸组件,就可以了。

由于此问题最近没有活动,因此已被自动标记为陈旧。 如果没有进一步的活动,它将关闭。 感谢您的贡献。

此页面是否有帮助?
0 / 5 - 0 等级