в библиотеке dnd kit для drag&drop при нажатии на вложенный компонент не срабатывает событие клика
У меня два компонента, родительский и дочерний, брал пример из документации, в дочернем компоненте у меня реализована логика по событию onClick раскрывать список элементов внутри, а в родительском используется функция onDragEnd которая и осуществляет драгэнддроп, при перетаскивании все работает, но при нажатии список не раскрывается, понимаю что это связано с всплытием и погружением но пока не могу додуматься как это пофиксить, возможно свойство какое-то есть в этой библиотеке, которая позволяет осуществлять подобное?
если заменить onClick на onDoubleClick, то все будет работать, но к сожалению нужно реализовать именно при клике один раз
Родительский компонент:
const Tree = ({ className, data, onDataLoad, onTabOpen, selectedId }: TTreeProps) => {
const [state, setState] = useState(data);
useEffect(()=>{
setState(data)
},[data])
//@ts-ignore
const handleDragEnd = (e)=>{
console.log('e handleDragEnd: ', e);
const {active, over} = e;
console.log("ACTIVE " + active.id);
console.log("OVER " + over.id);
if(active.id!==over.id){
setState((cities) => {
const oldIndex = cities.findIndex((city) => city.id === active.id);
const newIndex = cities.findIndex((city) => city.id === over.id);
return arrayMove(cities, oldIndex, newIndex);
});
}
};
return (
<div className={className}>
<TreeWrapper>
<DndContext collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
<SortableContext items={state} strategy={verticalListSortingStrategy}>
{state.map((item) => (
<TreeNode
{...item}
key={item.id}
onDataLoad={onDataLoad}
onTabOpen={onTabOpen}
selectedId={selectedId}
isHeading={item.isHeading}
/>
))}
</SortableContext>
</DndContext>
</TreeWrapper>
</div>
);
};
export default memo(Tree);
Дочерний компонент:
const TreeNode = ({
title,
children,
disabled,
isLeaf,
onDataLoad,
id,
loadStatus,
onTabOpen,
selectedId,
isHeading,
open = false,
}: TTreeNodeProps) => {
const ref = useRef<HTMLDivElement>(null);
const [contentVisible, setContentVisible] = useState<boolean>(open);
const [loadingStatus, setLoadingStatus] = useState<TLoadStatus | null>(loadStatus ?? null);
const hasChildren = !!children?.length || !isLeaf;
const {
attributes, listeners, setNodeRef, transform, transition
} = useSortable({id:id});
const style = {
transform: CSS.Transform.toString(transform),
transition
}
useEffect(() => {
setLoadingStatus(loadStatus ?? null);
if (loadStatus === LoadStatus.SUCCESS) {
setContentVisible(true);
}
}, [loadStatus]);
useEffect(() => {
if (open) setContentVisible(true);
}, [open]);
//@ts-ignore
const handleClick = (e) => {
console.log('e handleClick: ', e);
if (disabled) return;
if (!isLeaf && !children && onDataLoad) {
setLoadingStatus(LoadStatus.PROGRESS);
onDataLoad(id);
}
if (hasChildren) {
setContentVisible((prevState) => !prevState);
}
if (onTabOpen) {
ref?.current?.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "center" });
onTabOpen(id);
}
};
return (
<NodeWrapper ref={setNodeRef} style={style} {...attributes} {...listeners}>
<Heading $disabled={disabled} onClick={handleClick} $selected={selectedId === id} ref={ref}>
{isHeading ? (
<TitleStyled tag="span" size="title24" $disabled={disabled}>
{title}
</TitleStyled>
) : (
<TextStyled tag="p" size="text16" $disabled={disabled}>
{title}
</TextStyled>
)}
{hasChildren && !isHeading && (
<>
{loadingStatus === LoadStatus.PROGRESS ? (
<LoaderStyled className="ml4" />
) : (
<Arrow className="ml4" $open={contentVisible} />
)}
</>
)}
</Heading>
{children && contentVisible && (
<Tree
className="mt12"
data={children}
onDataLoad={onDataLoad}
onTabOpen={onTabOpen}
selectedId={selectedId}
/>
)}
</NodeWrapper>
);
};
export default TreeNode;