Reparenting
There are situations were you want to change the MuuriComponent parent
of the dragging Item while a drag is occurring. Here's an example in the gif below.
The implementation of this feature in Muuri-react manages to have the following characteristics
- The component is not
unmounted / re-mounted
(best performance). - Items don't have to be
configured
(very easy to implement). - The internal
state
of the Item is maintained (best developer experience).
How it works ๐
There are two types of events:
- When the Item is
dragged
to another MuuriComponent (but not released). - When the Item is
released
in another MuuriComponent.
You can interact with the first event in the Item via the useGrid
hook. Instead you have to interact with the second event through the MuuriComponent onSend
prop.
This division allows you to have the best performance and a better user experience. In the example of the gif, you can figure out which grid the Item is on, for changing the color of the right strip, only re-rendering the Item and not all the MuuriComponents.
Rules ๐
There are a few simple rules for implementing reparenting
- The Items must have unique
keys
between them, even if they do not share the same MuuriComponent parent. - You have to choose the MuuriComponents of which the Item can be a child by providing
group ids
. - When an Item changes parent you have to sync the state with the
onSend
prop.
Usage ๐
let's try to reproduce a part of the code of the example in gif, we focus on writing the onSend
function later.
When an Item is dragged
to another MuuriComponent as in the gif, we must update the Items state.
The MuuriComponents must re-render with their updated children, considering that the Item that has been dragged must be inserted in the new MuuriComponent of which it is now a child. Let's create the onSend method for the first MuuriComponent.
It is possible to simply insert the Item at the bottom as the last component (items.done.concat(transferredItem)
), without worrying about the position in which it was dragged. To keep the code cleaner we can create a function that works for each MuuriComponent and keep it in a different file.
We can now use the method for each MuuriComponent.
Hook: useGrid ๐
The useGrid
hook allow you to know which MuuriComponent the Item is on. See more here.
Exclusive drop ๐ซ
You can do some advanced stuff and control within which MuuriComponents a specific Item can be sorted and dragged into. To do that you can provide the groupId of these MuuriComponents in the dragSort prop.
In the example below you can send an Item from the first MuuriComponent to the second one, but not the opposite.
If you want to implement a more complex logic, different for each Item, you can provide a function
which receives the dragged Item as its first argument and should return an array of Muuri instances. You can easily access these instances by providing ids and groupIds to the muuriMap
.
Manual reparenting ๐ท
Reparenting is performed following a drag and drop. However, you can run it manually
through the Muuri instance. This way group control is not enabled and you have to call onSend manually. See more about Muuri here.
Note that you can also access the grids with the muuriMap.
How is that possible? ๐คจ
You may have wondered how it is possible that, during the reparenting, the Item
can be inserted among the children of the new MuuriComponent in any position (for example at the bottom), without worrying about the position in which it was dragged. This is because the order of the Item
components is separated from the order of the elements in the DOM. This allows to have a very simple implementation (In addition the Muuri-react diffing algorithm is optimized for insertions at the bottom).