refactor(react/svelte): use nodeLookup

This commit is contained in:
moklick
2023-11-14 15:52:48 +01:00
parent a147a20f6e
commit e798e94275
33 changed files with 166 additions and 127 deletions
@@ -43,7 +43,7 @@ const ConnectionLine = ({
const { fromNode, handleId, toX, toY, connectionMode } = useStore(
useCallback(
(s: ReactFlowStore) => ({
fromNode: s.nodesLookup.get(nodeId),
fromNode: s.nodeLookup.get(nodeId),
handleId: s.connectionStartHandle?.handleId,
toX: (s.connectionPosition.x - s.transform[0]) / s.transform[2],
toY: (s.connectionPosition.y - s.transform[1]) / s.transform[2],
@@ -1,7 +1,6 @@
import { isNumeric } from '@xyflow/system';
import type { BaseEdgeProps } from '../../types';
import EdgeText from './EdgeText';
const BaseEdge = ({
@@ -1,4 +1,4 @@
import { memo, useState, useMemo, useRef, type ComponentType, type KeyboardEvent } from 'react';
import { memo, useState, useMemo, useRef, type ComponentType, type KeyboardEvent, useCallback } from 'react';
import cc from 'classcat';
import { shallow } from 'zustand/shallow';
import { getMarkerId, elementSelectionKeys, XYHandle, type Connection, getEdgePosition } from '@xyflow/system';
@@ -53,26 +53,30 @@ export default (EdgeComponent: ComponentType<EdgeProps>) => {
const [updateHover, setUpdateHover] = useState<boolean>(false);
const [updating, setUpdating] = useState<boolean>(false);
const store = useStoreApi();
const edgePosition = useStore(function edgeSelector(state) {
const sourceNode = state.nodesLookup.get(source);
const targetNode = state.nodesLookup.get(target);
const edgePosition = useStore(
useCallback(
(state) => {
const sourceNode = state.nodeLookup.get(source);
const targetNode = state.nodeLookup.get(target);
if (!sourceNode || !targetNode) {
return null;
}
if (!sourceNode || !targetNode) {
return null;
}
const pos = getEdgePosition({
id,
sourceNode,
targetNode,
sourceHandle: sourceHandleId || null,
targetHandle: targetHandleId || null,
connectionMode: state.connectionMode,
onError: state.onError,
});
return pos;
}, shallow);
return getEdgePosition({
id,
sourceNode,
targetNode,
sourceHandle: sourceHandleId || null,
targetHandle: targetHandleId || null,
connectionMode: state.connectionMode,
onError: state.onError,
});
},
[source, target]
),
shallow
);
const markerStartUrl = useMemo(() => `url(#${getMarkerId(markerStart, rfId)})`, [markerStart, rfId]);
const markerEndUrl = useMemo(() => `url(#${getMarkerId(markerEnd, rfId)})`, [markerEnd, rfId]);
@@ -1,3 +1,8 @@
/*
* The Handle component is used to connect nodes. When the user mousedowns a handle, we start the connection process.
* The user can then drag the connection to another handle or node. When the user releases the mouse, we check if the
* connection is valid and if so, we call the onConnect callback.
*/
import { memo, HTMLAttributes, forwardRef, MouseEvent as ReactMouseEvent, TouchEvent as ReactTouchEvent } from 'react';
import cc from 'classcat';
import { shallow } from 'zustand/shallow';
+3 -3
View File
@@ -12,7 +12,7 @@ export function getMouseHandler(
return handler === undefined
? handler
: (event: MouseEvent) => {
const node = getState().nodes.find((n) => n.id === id)!;
const node = getState().nodeLookup.get(id)!;
handler(event, { ...node });
};
}
@@ -35,8 +35,8 @@ export function handleNodeClick({
unselect?: boolean;
nodeRef?: RefObject<HTMLDivElement>;
}) {
const { addSelectedNodes, unselectNodesAndEdges, multiSelectionActive, nodes, onError } = store.getState();
const node = nodes.find((n) => n.id === id)!;
const { addSelectedNodes, unselectNodesAndEdges, multiSelectionActive, nodeLookup, onError } = store.getState();
const node = nodeLookup.get(id);
if (!node) {
onError?.('012', errorMessages['error012'](id));
@@ -146,7 +146,7 @@ export default (NodeComponent: ComponentType<NodeProps>) => {
if (targetPosChanged) {
prevTargetPosition.current = targetPosition;
}
store.getState().updateNodeDimensions([{ id, nodeElement: nodeRef.current, forceUpdate: true }]);
store.getState().updateNodeDimensions(new Map([[id, { id, nodeElement: nodeRef.current, forceUpdate: true }]]));
}
}, [id, type, sourcePosition, targetPosition]);
@@ -1,3 +1,9 @@
/*
* This is a helper component for calling the onSelectionChange listener.
* It will only be mounted if the user has passed an onSelectionChange listener
* or is using the useOnSelectionChange hook.
* @TODO: Now that we have the onNodesChange and on EdgesChange listeners, do we still need this component?
*/
import { memo, useEffect } from 'react';
import { shallow } from 'zustand/shallow';
@@ -24,8 +30,6 @@ function areEqual(a: SelectorSlice, b: SelectorSlice) {
);
}
// This is just a helper component for calling the onSelectionChange listener.
// @TODO: Now that we have the onNodesChange and on EdgesChange listeners, do we still need this component?
const SelectionListener = memo(({ onSelectionChange }: SelectionListenerProps) => {
const store = useStoreApi();
const { selectedNodes, selectedEdges } = useStore(selector, areEqual);
@@ -1,3 +1,8 @@
/*
* This component helps us to update the store with the vlues coming from the user.
* We distinguish between values we can update directly with `useDirectStoreUpdater` (like `snapGrid`)
* and values that have a dedicated setter function in the store (like `setNodes`).
*/
import { useEffect } from 'react';
import { StoreApi } from 'zustand';
import { shallow } from 'zustand/shallow';
@@ -70,10 +75,10 @@ const selector = (s: ReactFlowState) => ({
reset: s.reset,
});
function useStoreUpdater<T>(value: T | undefined, setStoreState: (param: T) => void) {
function useStoreUpdater<T>(value: T | undefined, setStoreAction: (param: T) => void) {
useEffect(() => {
if (typeof value !== 'undefined') {
setStoreState(value);
setStoreAction(value);
}
}, [value]);
}