React-dnd: Предупреждение с вложенным DragSource

Созданный на 6 апр. 2016  ·  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 выполняет вызов setState во время вызова функции receiveProps?

triage wontfix

Самый полезный комментарий

На всякий случай это кому-то поможет: я столкнулся с этим, когда визуализировал компонент, который был источником перетаскивания в моем настраиваемом слое перетаскивания, потому что это было удобно. Я использовал компонент источника перетаскивания, потому что это была та же самая сущность, которую я пытался перетащить, поэтому для меня было логичным сохранить код «СУХИМ», повторно используя его. Я не думал о том, что в нем был весь код dragSource - оглядываясь назад, _ конечно_, я бы не хотел, чтобы источник перетаскивания КАК вещь отображалась в настраиваемом слое перетаскивания.

В конечном итоге я разделил свой компонент на «перетаскиваемую» версию, которая обернула базовый компонент, а затем использовал базовый компонент в моем настраиваемом слое перетаскивания. Больше никаких предупреждений, лучший код! 👍

Все 27 Комментарий

: +1:

Не могли бы вы представить проект, воспроизводящий проблему?

Я пытаюсь привести простой пример, и у меня возникают проблемы с воспроизведением вне моего частного проекта, над которым я работаю. @nihtalak , у вас есть репо на Github, в котором возникает проблема?

Вот крошечное репо, демонстрирующее описанное поведение: https://github.com/ebakan/react-dnd-nested-bug

Любопытно, что Component выдает эту ошибку только при прослушивании monitor.getItem() . Если он прослушивает monitor.isDragging() он будет работать правильно, как показано в этой ветке: https://github.com/ebakan/react-dnd-nested-bug/tree/no-error-with-is- перетаскивание

Он также выдаст ошибку при прослушивании monitor.getItemType() : https://github.com/ebakan/react-dnd-nested-bug/tree/error-with-get-item-type

@ebakan - интересно. Мне интересно, что вызывает появление этой ошибки в моем коде, который использует isDragging. Я делаю некоторые странные вещи с вложенным перетаскиваемым элементом, поэтому это может быть проявлением той же ошибки, которую вы видите. Спасибо за помощь в воспроизведении!

У меня тоже есть вложенные перетаскиваемые объекты, но я не уверен, что это проблема.
Кажется, создается новый магазин и код, который слушает. Я сделал видео, если это поможет:
http://screencast.com/t/qCrJRPAS2MYR

Обновление: обнаружил проблему, у меня был оставшийся слушатель, поэтому в моем случае это было не из-за response-dnd.
Update2: я заговорил слишком рано. После удаления оставшегося слушателя я все равно получаю предупреждение.

Я просто добавил Dnd к другому компоненту и заметил эту проблему даже без вложенных или нескольких перетаскиваемых компонентов.

Немного покопавшись, я обнаружил, что проблема связана с настраиваемым слоем перетаскивания, отображающим компонент при перетаскивании.

Если я помещаю текст вместо перетаскиваемого компонента, он работает нормально. Сам компонент является источником перетаскивания.

@jchristman @hakunin У меня нет вложенных перетаскиваемых файлов, но я столкнулся с 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 чтобы скрыть цель вместо добавления и удаления компонента при активном перетаскивании.

Я думаю , что может быть проблемой. Я проверю и дам вам знать. Это определенно та конструкция, которую я использую сейчас.

Нет - у меня проблема, когда происходит "падение". Затем он пытается повторно визуализировать компонент и выдает это предупреждение.

Получил такое же предупреждение, когда мой предварительный просмотр перетаскивания был компонентом, который был DragSource (чего я не должен делать).

@jchristman Вы когда-нибудь придумывали решение этой проблемы?

Я работаю с вложенными источниками перетаскивания и внезапно начал видеть эту ошибку при удалении вложенного ресурса.

Я могу привести пример, но хотел узнать, решил ли кто-нибудь проблему или нашел подходящее решение.

Получил такое же предупреждение, когда мой предварительный просмотр перетаскивания был компонентом, который был 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, response-dnd раздражается. Ожидается ли это, и мне нужно кое-что переосмыслить, или это ошибка dnd?

У меня точно такая же проблема. В некоторых случаях вы можете создать DragDropContext вокруг каждого вложенного перетаскиваемого объекта. Но это не сработает, если вам понадобится настраиваемый DragLayer ..

У меня та же ошибка, за исключением того, что я делаю вложенные dropTargets.
Осмотрев документацию, я попытался использовать

isOver (options): возвращает true, если выполняется операция перетаскивания, и указатель в настоящее время находится над владельцем. Вы можете при желании передать {shallow: true}, чтобы строго проверять, зависает ли только владелец, а не вложенная цель.

(с опцией shallow is true) в функции canDrop родительского dropTarget, и проблема исчезла. Я думаю, что то же самое можно применить и к другим сценариям.

@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

Соответствующий код здесь . Я собираюсь выяснить, почему в моем случае состояние может быть другим, чтобы вызвать повторную визуализацию ...

Я получаю эту проблему с помощью dragsource + droptarget, вложенного в droptarget.

Частично это произошло потому, что gaearon предусмотрел перетаскивание списка, сделав каждый элемент списка целью перетаскивания, а не превращая компонент списка в единственную цель перетаскивания, которая определяет, что делать, на основе положения перетаскивания. Второй способ - это то, как работает большинство других систем DnD, которые я видел.

На всякий случай это кому-то поможет: я столкнулся с этим, когда визуализировал компонент, который был источником перетаскивания в моем настраиваемом слое перетаскивания, потому что это было удобно. Я использовал компонент источника перетаскивания, потому что это была та же самая сущность, которую я пытался перетащить, поэтому для меня было логичным сохранить код «СУХИМ», повторно используя его. Я не думал о том, что в нем был весь код dragSource - оглядываясь назад, _ конечно_, я бы не хотел, чтобы источник перетаскивания КАК вещь отображалась в настраиваемом слое перетаскивания.

В конечном итоге я разделил свой компонент на «перетаскиваемую» версию, которая обернула базовый компонент, а затем использовал базовый компонент в моем настраиваемом слое перетаскивания. Больше никаких предупреждений, лучший код! 👍

@davidjoy woah, спасибо, что поделились! Я делаю то же самое, нужно попробовать!

@davidjoy Я тоже починил. Ваше предложение указывает на то, что не следует использовать DragSource и тому подобное для настраиваемого слоя. Я просто использовал голый компонент без DragSource в моем настраиваемом слое перетаскивания, и это помогло.

Эта проблема была автоматически помечена как устаревшая, поскольку в последнее время не было активности. Он будет закрыт, если больше не будет активности. Спасибо за ваш вклад.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги