Git Product home page Git Product logo

Comments (17)

remcotak avatar remcotak commented on May 8, 2024 5

@gaearon I'm having almost the same issue as this one. I have a simple sortable list that gets controlled by Redux. The sorting of the list is done almost the same way as this example.

Except the problem is, items can get removed from that list. The state gets updated with a complete new list retrieved from the store with less items. The unmount of the items happens and the dragEnd is not triggered.

The problem only occurs when a new list is presented with an item missing

from react-dnd.

gaearon avatar gaearon commented on May 8, 2024

I'll need some time to think on that, will look later in the evening.

from react-dnd.

gaearon avatar gaearon commented on May 8, 2024

Pardon for dragging my feet on this. I'm a bit busy with work stuff at the moment.
Is this urgent?

from react-dnd.

hakanderyal avatar hakanderyal commented on May 8, 2024

No problems, not urgent at all. I'm already the hacky way I mentioned, it works for my usecase.

from react-dnd.

gaearon avatar gaearon commented on May 8, 2024

OK, let me know if you have other ideas for fixing this as well.
I'll try to find some time next week to look into this!

from react-dnd.

hakanderyal avatar hakanderyal commented on May 8, 2024

Here is the a brain dump:

I see two different things here.

1- When source component is unmounted during drag, the endDrag defined on source component becomes irrelevant. Removing the source component may not be a common case, but for trello like functionality, I couldn't come up with any other solutions (Moving an item from one container to other). I thought about not removing, but hiding the source item while dragging, but couldn't find a reliable way of doing it.

While the action looks like moving an item, I'm essentially removing the item in one container, and adding a new one with same properties in another container. I also thought about if I can somehow carry the source item to another component without unmounting it, but haven't tried it, and don't know if it's even possible or feasible.

2- Assuming unmounting the source component during drag is the only way, I need to run a function when drag finishes. I'm achieving that by subscribing the DragDropStore of react-dnd in the parent component, and reacting to changes there. There isn't any way to get dragged item from the DRAG_END event, thus I added the lastDraggedItem stuff.

If there is way to solve 1 (endDrag defined on source item not working if it's unmounted while dragging), 2 becomes irrelevant (at least for this usecase).

This isn't a big problem for me, as subscribing to the DragDropStore is trivial.


On further thought, if unmounting the component while dragging is common enough usecase, may be we can offer some alternative syntactic sugar to define beginDrag & endDrag on parent component, and passing to child via props, and using them in DragDropMixin on child component.

I'm not sure if this is feasible or worth the effort either.

I'll give it some more thought.

from react-dnd.

gaearon avatar gaearon commented on May 8, 2024

I thought about not removing, but hiding the source item while dragging, but couldn't find a reliable way of doing it.

render() {
  var { isDragging } = this.getDragState(ItemTypes.CARD);
  if (isDragging) {
    return null;
  }

  ...
}

?

from react-dnd.

hakanderyal avatar hakanderyal commented on May 8, 2024

I'm sorry, I should have been more clear on that. The problem is not with hiding, but the application logic becomes becomes complicated with hiding, breaking the one way data flow.

On my usecase with trello-like app, when card is moved over to another list while dragging, I just fire an action to stores, removing it from one list and adding to another. React + Flux takes care of the rest.

There was all sorts of different usecases that my users came up with, user can drag card to another list first, than moving to original position without dropping, and than moving again etc. It's doable with hiding it, but becomes a lot more complicated than just handling it React + Flux.

Here is a short video of it in action: https://www.dropbox.com/s/852c0dyribbtykf/react-dnd-is-awesome.mov?dl=0

I'll think about it more tho.

Thanks.

from react-dnd.

gaearon avatar gaearon commented on May 8, 2024

Your example makes total sense.
I think we should fire endDrag ourselves if component is removed.

Why does this line not help us?
https://github.com/gaearon/react-dnd/blob/master/modules/utils/NativeDragDropSupport.js#L99

from react-dnd.

gaearon avatar gaearon commented on May 8, 2024

@nelix had a similar problem while implementing the mousemove backend (#53).

He tried to make a trello-like example and noticed that, once card is moved into another column, it no longer “knows” it's the one that is being dragged.

Here's the workaround I proposed in Gitter chat:

  1. Add key property to dragSource protocol (let's think later if we want to make it a breaking change, warn when it's missing, or use something like _nextId++ by default). It needs to be a string. The key uniquely identifies drag source in component tree, so even if component is removed and added in some other part of component tree, we can still recognize it as the current drag source.
  2. When drag begins, put that dragSource.key as draggedItemKey along with draggedItemType in action (and thus in Store). Read it from store in getStateFromDragDropStore so it gets into state.
  3. Change createDragDropMixin#getDragState to compare this._dragSources[type].key === this.state.draggedItemKey instead of looking at ownDraggedItemType.
  4. When component mounts, if we're in the middle of a drag and its type and key match draggedItemType and draggedItemKey, we need to establish it as “resurfaced” component instance for this particular drag source. We may want the backend to change its component reference to it. We need to ensure all events that were firing on previous component instance, now fire on this one.

To reiterate, I suggest that drag source can “jump onto” another component if that component has same _dragSources[type].key and original component is dead. We should probably fail hard if there are two components mounted at the same time with the same key (not sure).

I think this should also solve your issue. In your case, the card in another column will receive endDrag, although physically it's a different component.

from react-dnd.

gaearon avatar gaearon commented on May 8, 2024

Okay, I think I figured it out.

We will follow react-router's lead and make configureDragDrop static. Each method will accept component as first argument.

If drag source is unmounted while dragging, we will call endDrag with a null component argument.

from react-dnd.

nelix avatar nelix commented on May 8, 2024

Changes to the api to make it static are here #56

from react-dnd.

gaearon avatar gaearon commented on May 8, 2024

Fixed in 0.7.0.

@hakanderyal Can you give it a go?

from react-dnd.

hakanderyal avatar hakanderyal commented on May 8, 2024

I'm sorry that I couldn't join you guys, crunch time at work for the past week.

I'm hoping to try the new stuff and help wherever I can in a few days.

from react-dnd.

gaearon avatar gaearon commented on May 8, 2024

No problem. Thanks for bringing this to our attention :-)

from react-dnd.

Evoque avatar Evoque commented on May 8, 2024

Your example makes total sense.
I think we should fire endDrag ourselves if component is removed.

Why does this line not help us?
https://github.com/gaearon/react-dnd/blob/master/modules/utils/NativeDragDropSupport.js#L99

how can we fire endDrag ourselves?

from react-dnd.

Finec avatar Finec commented on May 8, 2024

Maybe this can help.

from react-dnd.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.