diff --git a/examples/react/src/examples/Middlewares/RestrictExtent.tsx b/examples/react/src/examples/Middlewares/RestrictExtent.tsx index beec2630..7a447414 100644 --- a/examples/react/src/examples/Middlewares/RestrictExtent.tsx +++ b/examples/react/src/examples/Middlewares/RestrictExtent.tsx @@ -1,4 +1,4 @@ -import { NodeChange, Panel, useNodeChangeMiddleware } from '@xyflow/react'; +import { NodeChange, experimental_useOnNodesChangeMiddleware } from '@xyflow/react'; import { useCallback, useState } from 'react'; export function RestrictExtent({ @@ -15,7 +15,7 @@ export function RestrictExtent({ maxY?: number; }) { const [isEnabled, setIsEnabled] = useState(false); - useNodeChangeMiddleware( + experimental_useOnNodesChangeMiddleware( useCallback( (changes: NodeChange[]) => { if (!isEnabled) return changes; @@ -36,7 +36,6 @@ export function RestrictExtent({ change.item = item; } } - return change; }); }, diff --git a/packages/react/src/components/BatchProvider/index.tsx b/packages/react/src/components/BatchProvider/index.tsx index 28f3aa4b..f6c6436c 100644 --- a/packages/react/src/components/BatchProvider/index.tsx +++ b/packages/react/src/components/BatchProvider/index.tsx @@ -35,7 +35,7 @@ export function BatchProvider[]; - for (const middleware of nodeChangeMiddleware.values()) { + for (const middleware of onNodesChangeMiddlewareMap.values()) { changes = middleware(changes); } - // for (const middleware of nodeSyncMiddleware.values()) { - // changes = middleware(changes); - // } - - // Do we always want to setNodes(next) or only when there are changes? - if (hasDefaultNodes) { setNodes(next); } diff --git a/packages/react/src/hooks/useMiddleware.ts b/packages/react/src/hooks/useMiddleware.ts index b2192564..a83a0c85 100644 --- a/packages/react/src/hooks/useMiddleware.ts +++ b/packages/react/src/hooks/useMiddleware.ts @@ -1,12 +1,12 @@ -import { NodeChange } from '@xyflow/system'; import { useEffect, useRef } from 'react'; +import type { EdgeChange, NodeChange } from '@xyflow/system'; + import { useStoreApi } from './useStore'; -import { Edge, Node } from '../types'; +import type { Edge, Node } from '../types'; /** * We identify each middleware with a symbol that is unique for each hook instance. */ - function useSymbol() { const symbol = useRef(); if (!symbol.current) { @@ -15,83 +15,40 @@ function useSymbol() { return symbol; } -export function useNodeChangeMiddleware( +export function experimental_useOnNodesChangeMiddleware( fn: (changes: NodeChange[]) => NodeChange[] ) { const store = useStoreApi(); const symbol = useSymbol(); useEffect(() => { - const { nodeChangeMiddleware } = store.getState(); - nodeChangeMiddleware.set(symbol.current!, fn); + const { onNodesChangeMiddlewareMap } = store.getState(); + onNodesChangeMiddlewareMap.set(symbol.current!, fn); }, [fn]); useEffect(() => { - const { nodeChangeMiddleware } = store.getState(); + const { onNodesChangeMiddlewareMap } = store.getState(); return () => { - nodeChangeMiddleware.delete(symbol.current!); + onNodesChangeMiddlewareMap.delete(symbol.current!); }; }, []); } -export function useNodeChangeMiddlewareDynamic( - fn: (changes: NodeChange[]) => NodeChange[] +export function experimental_useOnEdgesChangeMiddleware( + fn: (changes: EdgeChange[]) => EdgeChange[] ) { - const store = useStoreApi(); + const store = useStoreApi(); const symbol = useSymbol(); - const { nodeChangeMiddleware } = store.getState(); - nodeChangeMiddleware.delete(symbol.current!); - nodeChangeMiddleware.set(symbol.current!, fn); + useEffect(() => { + const { onEdgesChangeMiddlewareMap } = store.getState(); + onEdgesChangeMiddlewareMap.set(symbol.current!, fn); + }, [fn]); + + useEffect(() => { + const { onEdgesChangeMiddlewareMap } = store.getState(); + return () => { + onEdgesChangeMiddlewareMap.delete(symbol.current!); + }; + }, []); } - -// export function useEdgeChangeMiddleware(fn: (changes: EdgeChange[]) => EdgeChange[]) { -// const store = useStoreApi(); -// const symbol = useSymbol(); - -// useEffect(() => { -// const { edgeChangeMiddleware } = store.getState(); -// edgeChangeMiddleware.set(symbol.current!, fn); -// }, [fn]); - -// useEffect(() => { -// const { edgeChangeMiddleware } = store.getState(); -// return () => { -// edgeChangeMiddleware.delete(symbol.current!); -// }; -// }, []); -// } - -// export function useNodeSyncMiddleware(fn: (changes: NodeChange[]) => NodeChange[]) { -// const store = useStoreApi(); -// const symbol = useSymbol(); - -// useEffect(() => { -// const { nodeSyncMiddleware } = store.getState(); -// nodeSyncMiddleware.set(symbol.current!, fn); -// }, [fn]); - -// useEffect(() => { -// const { nodeSyncMiddleware } = store.getState(); -// return () => { -// nodeSyncMiddleware.delete(symbol.current!); -// }; -// }, []); -// } - -// export function useEdgeSyncMiddleware(fn: (changes: EdgeChange[]) => EdgeChange[]) { -// const store = useStoreApi(); -// const symbol = useSymbol(); - -// useEffect(() => { -// const { edgeSyncMiddleware } = store.getState(); -// edgeSyncMiddleware.set(symbol.current!, fn); -// }, [fn]); - -// useEffect(() => { -// const { edgeSyncMiddleware } = store.getState(); -// return () => { -// edgeSyncMiddleware.delete(symbol.current!); -// }; -// }, []); -// } diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts index 859e51e8..c6809d33 100644 --- a/packages/react/src/index.ts +++ b/packages/react/src/index.ts @@ -30,7 +30,10 @@ export { useConnection } from './hooks/useConnection'; export { useInternalNode } from './hooks/useInternalNode'; export { useNodeId } from './contexts/NodeIdContext'; -export { useNodeChangeMiddleware, useNodeChangeMiddlewareDynamic } from './hooks/useMiddleware'; +export { + experimental_useOnNodesChangeMiddleware, + experimental_useOnEdgesChangeMiddleware, +} from './hooks/useMiddleware'; export { applyNodeChanges, applyEdgeChanges } from './utils/changes'; export { isNode, isEdge } from './utils/general'; diff --git a/packages/react/src/store/index.ts b/packages/react/src/store/index.ts index 0391b041..28984d91 100644 --- a/packages/react/src/store/index.ts +++ b/packages/react/src/store/index.ts @@ -176,7 +176,7 @@ const createStore = ({ updateNodePositions: (nodeDragItems, dragging = false) => { const parentExpandChildren: ParentExpandChild[] = []; let changes = []; - const { nodeLookup, triggerNodeChanges, nodeChangeMiddleware } = get(); + const { nodeLookup, triggerNodeChanges, onNodesChangeMiddlewareMap } = get(); for (const [id, dragItem] of nodeDragItems) { // we are using the nodelookup to be sure to use the current expandParent and parentId value @@ -216,7 +216,7 @@ const createStore = ({ changes.push(...parentExpandChanges); } - for (const middleware of nodeChangeMiddleware.values()) { + for (const middleware of onNodesChangeMiddlewareMap.values()) { changes = middleware(changes); } diff --git a/packages/react/src/store/initialState.ts b/packages/react/src/store/initialState.ts index 917ef3e7..4ef80e74 100644 --- a/packages/react/src/store/initialState.ts +++ b/packages/react/src/store/initialState.ts @@ -147,10 +147,8 @@ const getInitialState = ({ debug: false, ariaLabelConfig: defaultAriaLabelConfig, - nodeChangeMiddleware: new Map(), - edgeChangeMiddleware: new Map(), - nodeSyncMiddleware: new Map(), - edgeSyncMiddleware: new Map(), + onNodesChangeMiddlewareMap: new Map(), + onEdgesChangeMiddlewareMap: new Map(), }; }; diff --git a/packages/react/src/types/store.ts b/packages/react/src/types/store.ts index a1ab5d64..36f0538f 100644 --- a/packages/react/src/types/store.ts +++ b/packages/react/src/types/store.ts @@ -153,10 +153,8 @@ export type ReactFlowStore[]) => NodeChange[]>; - edgeChangeMiddleware: Map[]) => EdgeChange[]>; - nodeSyncMiddleware: Map[]) => NodeChange[]>; - edgeSyncMiddleware: Map[]) => EdgeChange[]>; + onNodesChangeMiddlewareMap: Map[]) => NodeChange[]>; + onEdgesChangeMiddlewareMap: Map[]) => EdgeChange[]>; }; export type ReactFlowActions = {