-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Discussion: placement of handles and flow of data #498
Comments
Thank you for the thought-provoking issue. The core issue is that there is no clear recommendation for rolling up lots of lists into a single onDragEnd. It is difficult to make a recommendation as this library has no opinions about how you manage your state. Perhaps some additional hooks are a possible approach. There may even be some sort of nesting context approach that could work. We have aimed to keep the api as light as possible. The understanding is that if we return the id of the things that have been dragging then a consumer should be able to look up whatever data they need from that id. If that data is unavailable then that is a separate issue that needs to be managed by your implementation. A 'hack' to pass data now is to json encode your data as your id. Then you will get a json string as the id in your onDragEnd that you can parse. That is a hack, but it might be enough for you for now. I will no open up the api to allow direct passing of data until we explore this problem more |
Thank you for your prompt reply to the issue and offering the ‘hack’. I’ll discuss it with my team to see if they will be willing to adopt this approach, as it is still quite a bit less convenient compared what the currently library we are using is offering. I really like that you are trying to keep the api of the library as light as possible. And it is great that as you say it “this library has no opinions about how you manage your state”. My understanding that the core issue is that while react-beautiful-dnd does not have opinions about how state is managed, it is based on an assumption that all needed state is easily available to the onDragEnd either via a (redux) store, or via its placement in the same file as Draggable. As I indicated above, it is often not the case, as it is common in the React/Redux world to have some state inside the components, not Redux. And big code-bases are very unlikely to have DragDropContext and Draggable in the same file. Additional hooks/callbacks seem to be a good approach to solve the problem. Anyway, thanks again for putting so much effort in this great library. I think that resolving the issue will help a much wider adoption of the library. |
I prefer to add functions inside the ID, rather than using json encoding. Those functions capture a reference to the state at level of the droppable component. |
Interesting @Frozenlock. Does that work with our current setup? |
It should work. (I'm still on version 6.) The only caveat is that I'm using Clojurescript. |
Very interesting. We currently say it needs to be a string, but I do not think we do any string operations on the values. As long as referential equality is maintained it could work. This gives some great food for thought. Thanks @Frozenlock ! |
I need to work through whether that would enable people to get done what they want to. Using a function is a brilliant idea |
Playing a bit around (with multiple droppables this time), here's what seems to work inside the droppable ID:
Maps do not work. Maps will be passed to the Here's a cool hack however : |
Thanks for looking into this @Frozenlock. Glad to hear there is an option for people to use today. I think it would be a good idea to formalise this and provide a better first class api - as simple as an extra prop on a draggable that is passed on all the hooks which could contain anything - data or a function. For now it looks like users can hack the id to achieve this. Keep in mind though that this might have unexpected bugs as we assume the id is a string. Also, the id needs to be a unique identifier for the item so you will need to ensure that referential equality is never the same for multiple draggables |
Adding a prop with a name like:
to pass around to the hooks seems like a good idea. Not sure what to name the prop though |
This field would be available at the top level (with the |
Details to be confirmed, but something like that. |
Upgraded to 7.x.x, doesn't work anymore. 😢
Hopefully the new field will make its way in the next version. |
Thank you guys for the ideas you shared on this subject. Based on it, I decided to pass stringified objects. The The droppableId property of my droppableId={JSON.stringify({
id:'droppable_people',
table: 'people'
})} The droppableId property of one of my droppableId={JSON.stringify({
id:team.id,
table: 'team'
})} Passing the objects (stringified in this case) is useful to manage my hierarchies since I have different kinds of draggables, for example, the draggableId of my draggableId={JSON.stringify({
id:people.id,
table: 'people'
})} or like this: draggableId={JSON.stringify({
id:task.id,
table: 'task'
})} so on my const params = {
droppable: {
source: JSON.parse(source.droppableId),
destination: JSON.parse(destination.droppableId)
},
draggable: JSON.parse(result.draggableId)
}; and use it as needed, for example, on those conditions: if(params.droppable.source.id === 'droppable_people' &&
params.droppable.destination.table === 'team' ) and if(params.droppable.source.table === params.droppable.destination.table) |
I think we're going about this the wrong way. It's good that "this library has no opinions about how you manage your state" but I'm finding that, in most cases, it's in the context of The current suggestions are to pass up state from the Here's my suggestion. We leave I think this solves most use cases. Also, I think passing information about the relevant Here's my super hack to accomplish this for myself:
|
Super interesting @saiichihashimoto. Thank you |
First off, thank you for this great library. It's really well architected. I just wanted to +1 the approach @saiichihashimoto advocates. I think that both For Redux-driven apps the current top-level (This also applies to apps using HOC-style state management libraries like For example, an app might be structured something like: <DragDropContext>
<App>
...
...
<Query query="some list query">
{({ list, updateList }) => (
<Droppable ...>
{data.map(item => {
<Draggable ...>
...
</Draggable>
})
</Droppable>
)}
</Query>
</App>
</DragDropContext> In this case, the To update them from the Instead, it would be ideal to be able to just define an The same actually goes for So I think that both (@saiichihashimoto suggests separating them into two handlers, like That would make this library incredibly flexible, an unopinionated to any of the different approaches to state management. Thanks! |
There are some things that need to be thought through (such as what hooks are called when moving from one list to another), but I am liking the direction of this discussion. It seems like adding some callbacks could be a useful addition! |
This affects me as well. I have a case where the are multiple types of "droppables" nested within one another. Since I need to use one I'd think this could be implemented in a fairly straight forward way by allowing a prop to be set on the Droppable and Draggable components which gets passed in to the hook functions when they are called. I don't have a strong opinion on what this prop should be called.
|
This would be huge. I'm cloning and modifying a list before submitting a result to a database, which will, in-turn, result in the redux store being updated. A user will modify the list via an "edit" popup. The cloned list is held in the I was thinking that I could pass a bound function as the id (per suggestions earlier in this thread) for updating that state, but it seems like this hack is no longer possible. I gotta say, though, thank you for all of your excellent and creative work on this library. It's really fantastic. |
Whatever the path taken, I'd really appreciate if we can have the ability to pass arbitrary data (functions) around. |
will this feature be applied in last version ? |
UPDATE - turns out this seems to be causing an intermittent bug where the library throws an error at the start of a drag operation - cannot modify draggables during a drag operation. I'm stuck on v7.1.3 so can't say if this works with the current version, but the following sneaky hack seems to work. Provide an object as your {payload: arbitraryData, toString: () => "unique string"} Note this doesn't work with droppableId, due to the @Frozenlock I happen to also be doing this from ClojureScript (reagent), i.e. {:draggable-id #js {:payload my-data :toString (fn [] "...")}} The fact that this is a JS object means Reagent doesn't mess with the payload, so ClojureScript data comes through intact. I guess that doesn't apply to you as your payload would be a function, but worth mentioning. |
I am super open to suggestions for API proposals for this one. Would allowing passing a If the payload could be type any, then it could be a function that you could do what you want with |
@saiichihashimoto actually my workaround for this was adding a new middleware where I can get the store without connecting (to redux) the component that has the DragDropContext. |
A good time to make this change could be when we change the API to be hook based #871 |
This is definitely something I want to improve!! Starting small it might be sufficient to add a When we move to
|
@alexreardon Hi Alex. I'd really like to use this this |
I'm also looking to use the |
Is there any way we can move this forward? What would get us to some kind of action? |
I am busy working on some other core features right now. Once those land I am hoping to do some api redesign. Move to hooks etc. This would be a part of that |
Nice lib, thank you very much :) Here's what I ended up with, will call handlers in props of Droppables involved, both destination and source edit: removed code, see next comment |
Made the workaround from my previous comment into a gist, and
https://gist.github.com/mikkokaar/5caff07a33f4711aa3dd72a40b4e7a73 |
Thanks for providing the workaround. I ended up doing this.
Then in drop components
|
@cocacrave Thanks for the temporary solution to this! I've tried it using version 10.0.4 and it's working great. I was just wondering whether you've tried it using 10.1.0? I'm having problems with the drop area incorrectly calculating height and I'm struggling to work out if it's something that changed in the library which is incompatible with the work around or just some flex problem in my app. |
@llamamoray You're right. It's working fine on 10.0.4 but breaks badly on 10.1.0. Well that sucks... Hopefully the library implements this RFC before I need to upgrade the package. Things I noticed were the "placeholders" not being held in place on drag. And maybe as a result the drop moveTo is placed at a weird location. I have no clue why the workaround above would mess with positioning... doesn't make sense. |
I am working on a hooks api right now, and this sort of thing is being considered #871 |
Thank you to everyone for your input so far! I am keen for people thoughts: BackgroundCurrently we have ProposalAllow
Details
OrderMy current thinking is that the order of calling will be:
These calls will be synchronous so the order is not super important
|
All in all it sounds like a great approach. A few comments: Extra info about which
|
I'm on a flight to Japan for a nine day trip without my laptop so I won't be able to weigh in properly. |
ResponderThis is great news! I think it's much better to have all This makes it trivial to implement my previously given example :
Now each In my particular case, having PayloadI still think that having a payload would be very useful. But @JReinhold already made the case better than I could. |
@spatialvlad, @Frozenlock, @saiichihashimoto, @ianstormtaylor, @rhys-vdw, @JReinhold I have created a spike: #1250. It does not include a payload or @JReinhold's suggestion. However, it does set up the architecture. Right now it simply allows for a I am keen to get feedback |
I'm not exactly sure what all has happened in this discussion. But in my opinion the solution that makes this library flexible enough for any architecture is... For both (And for the So it sounds like maybe this is halfway towards the ideal? Which is a good first step. Although I'd still want them on the |
Was wondering on where this has landed. I started to look into this library to find out the onDragEnd must be at the top level ( which means it is outside of the context I need it to be in for the droppable) the solution posted back in 2019 sounded PERFECT , ( the logic for the drag and to be on the thing that accepts it makes sense) However, looking at the other issue linked to this, it looks like there was some snags with moving to public facing hooks, did that kill this issue? |
Same question here. I followed the discussions, but it looks that this did not make it in the main branch. Any update, do you think that you will be able to push it soon? Note: For folks still looking for this, I found the solution posted by @mikkokaar to help, till the final solution would be added: https://gist.github.com/mikkokaar/5caff07a33f4711aa3dd72a40b4e7a73 |
@alexreardon what is the current status of this? Still looking for feedback for the API or has this been implemented somewhere and I have overlooked it. I have added beautiful dnd into my project and have added the provider at a scope where I had my state logic. But now I need to drag items from within that scope to an entire different scope of a distant cousin component. If I move the provider up, I loose my state that needs updated. I am using react hooks for state and not redux. I am trying to tie all of this together with GraphQL using Apollo Client hooks as well. The main problem is that depending on what "layer" of droppables the item is dropped into, it runs different mutations based upon the layer and the id. I would like to keep this as simple as possible still to. But I think I might need to convert to React DnD to accomplish my goals as that ties the onDrop event to the droppable which receives the draggable props. |
I really like the great library that you guys have created. Our team is currently considering the option to start using react-beautiful-dnd instead of react-sortable-hoc we currently use.
However, it looks like there is a blocker for adopting your library for us due to inability to pass state/callback from Draggable into the onDragEnd of the DragDropContext. I hope I just missed the option in the documentation, but I did make a thorough search before opening the issue.
Your documentation recommends wrapping whole application with a DragDropContenxt. For most real-life production applications it means that DragDropContext will be multiple levels of hierarchy away form the Draggables. Even if multiple DragDropContexts are used, it is still very likely that the DragDropContext (probably with Droppable) will be not in the same file/component as the Draggables.
It is definitely not a big issue to create something like a top-level reducer inside of the onDragEnd that first filters results based on type, then applies corresponding logic, getting needed data from the Redux store. And this solution will work in some cases.
However, there are several drawbacks and even blockers with this approach:
It is extra work to get the Redux store data and process it in the corresponding onDragDrop reducer. This work was already probably conducted at the component level - Draggable or Droppable. And simply passing it would be much easier than trying to do it again.
Much bigger problem is that not all Component state lives in Redux store. This is a quite common and even recommened (e.g. reduxjs/redux#1287 ) behavior. This means that onDragEnd currently simply does not have a way to get needed state, unless substantial refactoring of existing code is done to put all needed state in a Redux store (and even then it might be not convenient).
Other libraries do not seem to have same limitation, as both offer a callback on the Draggable level to run after dragging ends.
E.g. React DnD offers endDrag for the DragSource. React-sortable-hoc has onSortEnd for the SortableComponent.
Your library looks superior to the above mentioned libraries in many aspects, but current limitation of not being able to define/pass a onDragEnd callback or at least some state from the Draggable is unfortunately greatly undermining its usability, especially if we are talking not about greenfield projects, but ones already developed and have lots of (presentational) state on the components level.
I hope I just missed some piece of the documentation and you can direct me where to have a look.
I did find something that seems related (but still does not seem to answer my question):
#120
#466
It would be really great if there actually was some way to pass a callback from Draggable. I would appreciate if you could help me find out how to do this.
Thanks.
The text was updated successfully, but these errors were encountered: