diff --git a/examples/react/src/examples/UseNodesData/index.tsx b/examples/react/src/examples/UseNodesData/index.tsx index 91cc1f94..dc0b43dd 100644 --- a/examples/react/src/examples/UseNodesData/index.tsx +++ b/examples/react/src/examples/UseNodesData/index.tsx @@ -20,8 +20,8 @@ export type ResultNode = Node<{}, 'result'>; export type UppercaseNode = Node<{ text: string }, 'uppercase'>; export type MyNode = TextNode | ResultNode | UppercaseNode; -export function isTextNode(node: any): node is TextNode { - return node.type === 'text'; +export function isTextNode(node: any): node is TextNode | UppercaseNode { + return node.type === 'text' || node.type === 'uppercase'; } const nodeTypes = { diff --git a/examples/svelte/src/routes/examples/usenodesdata/+page.svelte b/examples/svelte/src/routes/examples/usenodesdata/+page.svelte index fc85ee26..91fd8432 100644 --- a/examples/svelte/src/routes/examples/usenodesdata/+page.svelte +++ b/examples/svelte/src/routes/examples/usenodesdata/+page.svelte @@ -5,8 +5,8 @@ type UppercaseNodeType = Node<{ text: string }, 'uppercase'>; type ResultNodeType = Node<{}, 'result'>; - export function isTextNode(node: any): node is TextNodeType { - return node.type === 'text'; + export function isTextNode(node: any): node is TextNodeType | UppercaseNode { + return node.type === 'text' || node.type === 'uppercase'; } export type MyNode = TextNodeType | UppercaseNodeType | ResultNodeType; diff --git a/packages/react/src/hooks/useNodesData.ts b/packages/react/src/hooks/useNodesData.ts index c43a60cc..7472cbf7 100644 --- a/packages/react/src/hooks/useNodesData.ts +++ b/packages/react/src/hooks/useNodesData.ts @@ -1,15 +1,9 @@ import { useCallback } from 'react'; -import { shallow } from 'zustand/shallow'; +import { shallowNodeData } from '@xyflow/system'; import { useStore } from '../hooks/useStore'; import type { Node } from '../types'; -export interface NodeDataReturn { - id: string; - type: NodeType['type']; - data: NodeType['data']; -} - /** * Hook for receiving data of one or multiple nodes * @@ -46,7 +40,7 @@ export function useNodesData(nodeIds: any): any { }, [nodeIds] ), - shallow + shallowNodeData ); return nodesData; diff --git a/packages/svelte/src/lib/hooks/useNodesData.ts b/packages/svelte/src/lib/hooks/useNodesData.ts index c11ef308..254a70fd 100644 --- a/packages/svelte/src/lib/hooks/useNodesData.ts +++ b/packages/svelte/src/lib/hooks/useNodesData.ts @@ -1,22 +1,9 @@ import { derived, type Readable } from 'svelte/store'; +import { shallowNodeData } from '@xyflow/system'; import type { Node } from '$lib/types'; import { useStore } from '$lib/store'; -function areNodesDataEqual(a: any[], b: any[]) { - if (a.length !== b.length) { - return false; - } - - for (let i = 0; i < a.length; i++) { - if (a[i].data !== b[i].data) { - return false; - } - } - - return true; -} - /** * Hook for receiving data of one or multiple nodes * @@ -51,7 +38,7 @@ export function useNodesData(nodeIds: any): any { } } - if (!areNodesDataEqual(nextNodesData, prevNodesData)) { + if (!shallowNodeData(nextNodesData, prevNodesData)) { prevNodesData = nextNodesData; set(isArrayOfIds ? nextNodesData : nextNodesData[0] ?? null); } diff --git a/packages/system/src/utils/index.ts b/packages/system/src/utils/index.ts index cd66e951..2640195d 100644 --- a/packages/system/src/utils/index.ts +++ b/packages/system/src/utils/index.ts @@ -7,3 +7,4 @@ export * from './marker'; export * from './node-toolbar'; export * from './store'; export * from './types'; +export * from './shallow-node-data'; diff --git a/packages/system/src/utils/shallow-node-data.ts b/packages/system/src/utils/shallow-node-data.ts new file mode 100644 index 00000000..2faf1c1a --- /dev/null +++ b/packages/system/src/utils/shallow-node-data.ts @@ -0,0 +1,20 @@ +import { NodeBase } from '../types'; + +type NodeData = Pick; + +export function shallowNodeData(a: NodeData | NodeData[], b: NodeData | NodeData[]) { + const _a = Array.isArray(a) ? a : [a]; + const _b = Array.isArray(b) ? b : [b]; + + if (_a.length !== _b.length) { + return false; + } + + for (let i = 0; i < _a.length; i++) { + if (_a[i].id !== _b[i].id || _a[i].type !== _b[i].type || !Object.is(_a[i].data, _b[i].data)) { + return false; + } + } + + return true; +}