Se você tiver um DragSource dentro de um componente que também é um DragSource (ou seja, arraste algo dentro de um draggable), sempre que o componente pai for arrastado, o seguinte aviso aparecerá.
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
Um exemplo disso seria:
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>
);
}
}
Eu acredito que o problema decorre do fato de que renderizar novamente o componente pai faz com que a chamada de DragSource filha faça uma chamada para setState durante a chamada de função receiveProps.
: +1:
Você pode fornecer um projeto reproduzindo o problema?
Estou tentando produzir um exemplo simples e estou tendo problemas para reproduzir fora do meu projeto privado em que estou trabalhando. @nihtalak , você tem um repositório no Github que produz o problema?
Aqui está um minúsculo repo exibindo o comportamento descrito: https://github.com/ebakan/react-dnd-nested-bug
Curiosamente, o Component
só lança esse erro quando está escutando monitor.getItem()
. Se estiver escutando monitor.isDragging()
, funcionará corretamente, conforme mostrado neste branch: https://github.com/ebakan/react-dnd-nested-bug/tree/no-error-with-is- arrastando
Ele também gerará o erro ao ouvir monitor.getItemType()
: https://github.com/ebakan/react-dnd-nested-bug/tree/error-with-get-item-type
@ebakan - interessante. Estou me perguntando o que está fazendo com que esse bug apareça no meu código, que usa isDragging. Estou fazendo algumas coisas erradas com o draggable aninhado, então pode ser uma manifestação do mesmo bug que você está vendo. Obrigado pela ajuda na reprodução!
Também aninhei draggables, mas não tenho certeza se esse é o problema.
Parece estar criando uma nova loja e o código que está ouvindo. Fiz um vídeo se isso ajudar:
http://screencast.com/t/qCrJRPAS2MYR
Update: encontrei o problema, eu tinha um ouvinte restante, então no meu caso não foi devido ao react-dnd.
Update2: falei muito cedo. Ao remover o ouvinte restante, ainda recebo o aviso.
Acabei de adicionar Dnd a outro componente e notei esse problema mesmo sem componentes de arrastar aninhados ou múltiplos.
Depois de pesquisar um pouco, descobri que o problema está relacionado à camada de arrastar personalizada que renderiza o componente enquanto é arrastado.
Se eu colocar texto em vez do componente que está sendo arrastado, ele funcionará bem. O próprio componente é a origem do arrasto.
@jchristman @hakunin Não tenho draggables aninhados, mas encontrei Cannot update during an existing state transition
quando tive um destino de soltar renderizado condicionalmente com base em isDragging
. Isso poderia ser o caso em algum dos seus exemplos? Algo mais ou menos assim:
render() {
var dropZone;
if (this.props.isDragging) dropZone = <MyDropTarget />;
return <div>
<MyDragSource />
{dropZone}
</div>
}
Acabou trabalhando em torno dele usando display: none/block
para ocultar o alvo em vez de adicionar e remover o componente quando arrastar está ativo.
Acho que esse pode ser o problema. Vou verificar e lhe aviso. Essa é definitivamente a construção que estou usando agora.
Não - estou entendendo o problema quando a "queda" acontece. Em seguida, ele tenta renderizar novamente o componente e lança este aviso.
Recebi o mesmo aviso quando minha visualização de arrastar era um componente que era um DragSource (o que não devo fazer).
@jchristman , você já encontrou uma solução para isso?
Estou trabalhando com dragSources aninhados e de repente comecei a ver este erro ao soltar o recurso aninhado.
Posso fornecer um exemplo, mas gostaria de ver se alguém havia resolvido o problema ou tinha uma solução alternativa adequada.
Recebi o mesmo aviso quando minha visualização de arrastar era um componente que era um DragSource (o que não devo fazer).
Obrigado @arjunu meu aviso foi causado por isso!
Eu ainda tenho isso ocasionalmente, então acho que algum outro motivo deve ser consertado também. Pode ser da minha parte :)
@ gharwood1 , estou apenas vivendo com o problema até que possa ser consertado. Uma vez, passei algumas horas tentando realmente entender esta biblioteca para que eu pudesse puxar a solicitação de uma correção, mas é muito complexo, então segui em frente. Eu simplesmente não tenho tempo ... :-(
@gaearon Não tenho um projeto feito que seja capaz de alguém derrubar, mas acho que posso conseguir fazer um, se necessário.
Basicamente, o que estou tentando fazer aqui é válido:
Se eu desabilitar a condicional na linha 64 está tudo bem
if (this.props.draggingSubject){
effectiveChildren.push(this.props.draggingSubject);
}
mas no minuto em que os resultados do evento de arrastar começam a modificar adereços e renderização de componentes, o aviso acima começa a ser cuspido com frequência.
Eu não deveria estar fazendo isso?
O caso de uso é basicamente "visualizar" o item arrastado no momento no destino de soltar. O que está acima é uma prova de conceito - não conectado à loja Redux ainda, já que não tenho certeza se isso é mesmo válido.
Hm, parece que está tudo bem se eu mantiver minhas alterações locais para SubjectDisplayContent
, mas os avisos começarão a acontecer se as alterações se estenderem para SubjectDisplay
. Então, basicamente, se um dropTarget envia props para baixo que modificam um dropTarget diferente , react-dnd fica irritado. Isso é esperado e preciso repensar algumas coisas ou é um bug do dnd?
Estou enfrentando exatamente o mesmo problema. O que você pode fazer em algumas situações é criar um DragDropContext
ao redor de cada arrastável aninhado. Mas isso não funciona assim que você deseja um DragLayer personalizado.
Recebi o mesmo erro, exceto que estou fazendo um dropTargets aninhado.
Depois de examinar a documentação, tentei usar
isOver (opções): Retorna verdadeiro se houver uma operação de arrastar em andamento e o ponteiro estiver pairando sobre o proprietário. Você pode, opcionalmente, passar {shallow: true} para verificar estritamente se apenas o proprietário está sendo pairado, ao contrário de um alvo aninhado.
(com a opção shallow is true) na função canDrop do dropTarget pai, e o problema foi embora. Eu acho que o mesmo poderia ser aplicado a alguns outros cenários.
@jchenjc Tentei fazer isso, mas não funcionou para mim. Para ser honesto, minha situação é extremamente complicada com visualização de arrastar aninhada + fonte de arrastar + destino de soltar que precisa funcionar em listas.
FWIW: Eu tenho fontes de arrastar aninhadas e uma camada de arrastar personalizada. Quando removo a camada de arrastar personalizada, a mensagem desaparece. Ao inspecionar o rastreamento de pilha, parece que o problema está aqui:
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
O código relevante está aqui . Vou ver por que o estado pode ser diferente no meu caso para acionar uma re-renderização ...
Com um dragsource + droptarget aninhado em um droptarget, recebo esse problema.
Parte da razão pela qual isso aconteceu é porque gaearon imaginou fazer a lista de arrastar e soltar tornando cada item da lista um destino de soltar, em vez de tornar o componente da lista um único destino de soltar que determina o que fazer com base na posição do foco de arrastar. A última maneira é como a maioria dos outros sistemas DnD que já vi fazem as coisas.
Caso isso ajude alguém: eu encontrei isso quando estava renderizando um componente que era uma fonte de arrastar em minha camada de arrastar personalizada porque era conveniente. Usei o componente arrastar fonte porque era a mesma entidade que eu estava tentando arrastar, então fazia sentido para mim manter o código "DRY" reutilizando-o. Eu não pensei sobre o fato de que ele tinha todo o código dragSource nele - olhando para trás, _é claro_ eu não gostaria de um código de arrastar como a coisa a ser renderizada na camada de arrastar personalizada.
Por fim, divido meu componente em uma versão "arrastável" que envolve o componente base e, em seguida, usei o componente base em minha camada de arrastar personalizada. Sem mais avisos, melhor código! 👍
@davidjoy woah, obrigado por compartilhar! Estou fazendo a mesma coisa, preciso tentar também!
@davidjoy Acabei de consertar o meu também. Sua sugestão aponta para não usar DragSource e tal para a camada personalizada. O que fiz foi simplesmente usar o componente simples sem DragSource na minha camada de arrastar personalizada e isso resolveu o problema.
Este problema foi marcado automaticamente como obsoleto porque não teve atividades recentes. Ele será fechado se nenhuma outra atividade ocorrer. Obrigado por suas contribuições.
Comentários muito úteis
Caso isso ajude alguém: eu encontrei isso quando estava renderizando um componente que era uma fonte de arrastar em minha camada de arrastar personalizada porque era conveniente. Usei o componente arrastar fonte porque era a mesma entidade que eu estava tentando arrastar, então fazia sentido para mim manter o código "DRY" reutilizando-o. Eu não pensei sobre o fato de que ele tinha todo o código dragSource nele - olhando para trás, _é claro_ eu não gostaria de um código de arrastar como a coisa a ser renderizada na camada de arrastar personalizada.
Por fim, divido meu componente em uma versão "arrastável" que envolve o componente base e, em seguida, usei o componente base em minha camada de arrastar personalizada. Sem mais avisos, melhor código! 👍