Merge pull request #5336 from xyflow/fix/useNodeConnections

Fix useNodeConnections callbacks firing only when returned signal is used
This commit is contained in:
Moritz Klack
2025-06-16 14:32:59 +02:00
committed by GitHub
3 changed files with 41 additions and 5 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@xyflow/svelte': patch
---
Fix `useNodeConnections` callbacks firing only when returned signal is used
@@ -16,6 +16,15 @@
handleType: 'target' handleType: 'target'
}); });
useNodeConnections({
onConnect: (connection) => {
console.log('Connection made:', connection);
},
onDisconnect: (connection) => {
console.log('Connection disconnected:', connection);
}
});
let nodeData = $derived( let nodeData = $derived(
useNodesData<MyNode>(connections.current.map((connection) => connection.source)) useNodesData<MyNode>(connections.current.map((connection) => connection.source))
); );
@@ -17,6 +17,8 @@ type UseNodeConnectionsParams = {
onDisconnect?: (connections: Connection[]) => void; onDisconnect?: (connections: Connection[]) => void;
}; };
type ConnectionMap = Map<string, NodeConnection>;
const initialConnections: NodeConnection[] = []; const initialConnections: NodeConnection[] = [];
/** /**
@@ -42,26 +44,46 @@ export function useNodeConnections({
const contextNodeId = getContext<string>('svelteflow__node_id'); const contextNodeId = getContext<string>('svelteflow__node_id');
const nodeId = id ?? contextNodeId; const nodeId = id ?? contextNodeId;
let prevConnections: Map<string, NodeConnection> = new Map(); let connectionMaps: { previous: ConnectionMap; next: ConnectionMap } = {
previous: new Map(),
next: new Map()
};
let connectionsArray: NodeConnection[] = initialConnections; let connectionsArray: NodeConnection[] = initialConnections;
const connections = $derived.by(() => { const connections = $derived.by(() => {
// eslint-disable-next-line @typescript-eslint/no-unused-expressions // eslint-disable-next-line @typescript-eslint/no-unused-expressions
edges; edges;
const prevConnections = connectionMaps.next;
const nextConnections = const nextConnections =
connectionLookup.get( connectionLookup.get(
`${nodeId}${handleType ? (handleId ? `-${handleType}-${handleId}` : `-${handleType}`) : ''}` `${nodeId}${handleType ? (handleId ? `-${handleType}-${handleId}` : `-${handleType}`) : ''}`
) ?? new Map(); ) ?? new Map();
if (!areConnectionMapsEqual(nextConnections, prevConnections)) { if (!areConnectionMapsEqual(nextConnections, prevConnections)) {
if (onConnect) handleConnectionChange(nextConnections, prevConnections, onConnect); connectionMaps = {
if (onDisconnect) handleConnectionChange(prevConnections, nextConnections, onDisconnect); previous: prevConnections,
next: nextConnections
prevConnections = nextConnections; };
connectionsArray = Array.from(nextConnections.values() || initialConnections); connectionsArray = Array.from(nextConnections.values() || initialConnections);
} }
return connectionsArray; return connectionsArray;
}); });
$effect(() => {
// We subscribe to changes to the connections only when onConnect/onDisconnect are provided
if (onConnect) {
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
connections;
handleConnectionChange(connectionMaps.next, connectionMaps.previous, onConnect);
}
if (onDisconnect) {
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
connections;
handleConnectionChange(connectionMaps.previous, connectionMaps.next, onDisconnect);
}
});
return { return {
get current() { get current() {
return connections; return connections;