How to avoid an event bubbling in nested components with React DnD Beautiful Library?

Viewed 396

I have a problem with event bubbling. I'm using React DnD Beautiful to sort a vertical list. I have a list of collections and within each collection there is a nested list of services.

I can either drag and drop collections to sort them vertically or drag and drop services only within a correspondent collection to sort them as well.

When I drag collections, everything is working properly. But when I try to drag services, sometimes instead of grabbing a service, I grab a whole collection. It happens due to an event bubbling. Usually, I would solve the problem with e.stopPropagation(), but it seems not to work.

React DnD Beautiful uses {...provided.dragHandleProps} where they, for instance, handle onDragStart. I tried to customize it, but it didn't work. I wonder, whether I'm just customizing it wrong?

Beneath is a pseudocode.

COLLECTION LIST

function SortableCollectionsList() {
    const styles = useStyles();
    const {sortedCollections, onDragEnd} = useSortedCollections()
    return (
        <div className={"collectionListWrapper"}>
            <DragDropContext onDragEnd={onDragEnd}>
                <Droppable droppableId="droppable" direction="vertical">
                    {(provided, snapshot) => (
                        // List of all collections
                        <List
                            ref={provided.innerRef}
                            {...provided.droppableProps}
                            aria-labelledby="nested-list-subheader"
                            subheader={
                                <ListSubheader component="div" id="nested-list-subheader">
                                    Drag and drop collections and services
                                </ListSubheader>
                            }
                            className={styles.root}
                        >
                            {sortedCollections
                                .map(({id, name, showName, logo, services: serviceIds}, index) =>
                                    <Draggable key={id} draggableId={id} index={index}>
                                        {(provided, snapshot) => (
                                            <>
                                                {/*One collection containing a list of services*/}
                                                <ListItem key={id}
                                                          ref={provided.innerRef}
                                                          {...provided.draggableProps}
                                                          {...provided.dragHandleProps}
                                                          onDragStart={(e) => {
                                                              e.stopPropagation(),
                                                                  provided.dragHandleProps.onDragStart(e),
                                                                  console.log("collections stop propagation")
                                                          }}
                                                    
                                                          className={styles.collection}
                                                >
                                                    {/*List of services within one collection*/}
                                                    <SortableServicesList {...{
                                                        serviceIds,
                                                        collectionId: id,
                                                        title: name
                                                    }}/>
                                                </ListItem>
                                            </>
                                        )}
                                    </Draggable>
                                )}
                            {provided.placeholder}
                        </List>
                    )}
                </Droppable>
            </DragDropContext>
        </div>
    )
}

SERVICES WITHIN EACH COLLECTION

function SortableServicesList({serviceIds, collectionId, title}) {
    const {sortedServices, onDragEnd} = useSortedServices(serviceIds, collectionId)

    const classes = useStyles();
    const [open, setOpen] = React.useState(true);

    const handleClick = () => {
        setOpen(!open);
    };

    return (
        // A collection LIST (one list) of services
        <List
            component="nav"
            aria-labelledby="nested-list-subheader"
            className={classes.root}
        >
            <ListItem button onClick={handleClick}>
                <DragIndicatorIcon fontSize="small"/>
                <ListItemText primary={title}/>
                {open ? <ExpandLess/> : <ExpandMore/>}
            </ListItem>

            <Collapse in={open} timeout="auto" unmountOnExit>
                <DragDropContext onDragEnd={onDragEnd}>
                    <Droppable droppableId="droppable" direction="vertical">
                        {(provided, snapshot) => (
                            // LIST AS A DROPPABLE CONTAINER FOR THE SERVICES
                            <List ref={provided.innerRef}
                                  style={getContainerStyle(snapshot.isDraggingOver)}
                                  {...provided.droppableProps}
                                  className="collectionItems"
                                  component="div"
                                  disablePadding
                            >
                                {sortedServices
                                    .map(({id, name}, index) =>

                                        // A LIST ITEM AS A DRAGGABLE SERVICE
                                        <Draggable key={id} draggableId={id} index={index}>
                                            {(provided, snapshot) => (
                                                <>
                                                    <ListItem button
                                                              key={id}
                                                              ref={provided.innerRef}
                                                              {...provided.draggableProps}
                                                              {...provided.dragHandleProps}
                                                              onDragStart={(e) => {
                                                                  e.stopPropagation(),
                                                                      provided.dragHandleProps.onDragStart(e),
                                                                  console.log("services stop propagation")
                                                              }}
                                                              style={getServiceCardStyle(
                                                                  snapshot.isDragging,
                                                                  provided.draggableProps.style,
                                                              )}
                                                              className={classes.nested}
                                                    >
                                                        <DragIndicatorIcon fontSize="small"/>
                                                        <ListItemText primary={name}/>
                                                    </ListItem>
                                                </>
                                            )}
                                        </Draggable>
                                    )}
                                {provided.placeholder}
                            </List>
                        )}
                    </Droppable>
                </DragDropContext>
            </Collapse>
        </List>
    )
}

As you can observe, I'm also confused where should I define my custom event. For now, I just did the same for both collections and services, namely this:

onDragStart={(e) => {
                                                                  e.stopPropagation(),
                                                                      provided.dragHandleProps.onDragStart(e),
                                                                  console.log("services stop propagation")
                                                              }}

And also it doesn't console.log() anything.

Ty for your help. I'm actually a beginner and it is very confusing for me, even if it is easy.

0 Answers
Related