Если у вас есть 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?
: +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 У меня нет проекта, который можно было бы
В принципе, то, что я пытаюсь сделать здесь, действительно:
Если я отключу условие в строке 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 в моем настраиваемом слое перетаскивания, и это помогло.
Эта проблема была автоматически помечена как устаревшая, поскольку в последнее время не было активности. Он будет закрыт, если больше не будет активности. Спасибо за ваш вклад.
Самый полезный комментарий
На всякий случай это кому-то поможет: я столкнулся с этим, когда визуализировал компонент, который был источником перетаскивания в моем настраиваемом слое перетаскивания, потому что это было удобно. Я использовал компонент источника перетаскивания, потому что это была та же самая сущность, которую я пытался перетащить, поэтому для меня было логичным сохранить код «СУХИМ», повторно используя его. Я не думал о том, что в нем был весь код dragSource - оглядываясь назад, _ конечно_, я бы не хотел, чтобы источник перетаскивания КАК вещь отображалась в настраиваемом слое перетаскивания.
В конечном итоге я разделил свой компонент на «перетаскиваемую» версию, которая обернула базовый компонент, а затем использовал базовый компонент в моем настраиваемом слое перетаскивания. Больше никаких предупреждений, лучший код! 👍