fix: ensure drag handlers update when nodes selection changes programmatically

Fixes #4841

When nodes were programmatically selected (e.g., adding a new node with `selected: true`),
the nodes selection rectangle would appear but dragging it would not work.

Changes:
- Consolidated duplicate effect hooks in useDrag into a single useIsomorphicLayoutEffect
- Added `disabled` parameter to useDrag to allow external control
- NodesSelection now passes `disabled: !shouldRender` to useDrag
- Improved condition clarity with `shouldRender` variable

This ensures drag handlers are properly set up when nodeRef.current becomes available,
even when the selection state changes after the initial render.
This commit is contained in:
ysds
2026-01-24 02:29:02 +09:00
parent cf2d4be3f5
commit 03b8e1ef19
2 changed files with 25 additions and 15 deletions

View File

@@ -51,11 +51,14 @@ export function NodesSelection<NodeType extends Node>({
}
}, [disableKeyboardA11y]);
const shouldRender = !userSelectionActive && width !== null && height !== null;
useDrag({
nodeRef,
disabled: !shouldRender,
});
if (userSelectionActive || !width || !height) {
if (!shouldRender) {
return null;
}

View File

@@ -3,6 +3,7 @@ import { XYDrag, type XYDragInstance } from '@xyflow/system';
import { handleNodeClick } from '../components/Nodes/utils';
import { useStoreApi } from './useStore';
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';
type UseDragParams = {
nodeRef: RefObject<HTMLDivElement>;
@@ -51,23 +52,29 @@ export function useDrag({
});
}, []);
useEffect(() => {
useIsomorphicLayoutEffect(() => {
if (disabled) {
xyDrag.current?.destroy();
} else if (nodeRef.current) {
xyDrag.current?.update({
noDragClassName,
handleSelector,
domNode: nodeRef.current,
isSelectable,
nodeId,
nodeClickDistance,
});
return () => {
xyDrag.current?.destroy();
};
return;
}
}, [noDragClassName, handleSelector, disabled, isSelectable, nodeRef, nodeId]);
if (!nodeRef.current || !xyDrag.current) {
return;
}
xyDrag.current.update({
noDragClassName,
handleSelector,
domNode: nodeRef.current,
isSelectable,
nodeId,
nodeClickDistance,
});
return () => {
xyDrag.current?.destroy();
};
}, [noDragClassName, handleSelector, disabled, isSelectable, nodeRef, nodeId, nodeClickDistance]);
return dragging;
}