refactor(useUpdateNodeInternals): make it easier to use #2008
This commit is contained in:
@@ -1,30 +1,33 @@
|
|||||||
import React, { memo, FC, useMemo, CSSProperties } from 'react';
|
import React, { memo, FC, useMemo, CSSProperties, useState } from 'react';
|
||||||
import { Handle, Position, NodeProps } from 'react-flow-renderer';
|
import { Handle, Position, NodeProps, useUpdateNodeInternals } from 'react-flow-renderer';
|
||||||
|
|
||||||
const nodeStyles: CSSProperties = { padding: 10, border: '1px solid #ddd' };
|
const nodeStyles: CSSProperties = { padding: 10, border: '1px solid #ddd' };
|
||||||
|
|
||||||
const CustomNode: FC<NodeProps> = ({ data }) => {
|
const CustomNode: FC<NodeProps> = ({ id }) => {
|
||||||
|
const [handleCount, setHandleCount] = useState(1);
|
||||||
|
const updateNodeInternals = useUpdateNodeInternals();
|
||||||
|
|
||||||
const handles = useMemo(
|
const handles = useMemo(
|
||||||
() =>
|
() =>
|
||||||
Array.from({ length: data.handleCount }, (x, i) => {
|
Array.from({ length: handleCount }, (x, i) => {
|
||||||
const handleId = `handle-${i}`;
|
const handleId = `handle-${i}`;
|
||||||
return (
|
return <Handle key={handleId} type="source" position={Position.Right} id={handleId} style={{ top: 10 * i }} />;
|
||||||
<Handle
|
|
||||||
key={handleId}
|
|
||||||
type="source"
|
|
||||||
position={Position.Right}
|
|
||||||
id={handleId}
|
|
||||||
style={{ top: 10 * i + data.handlePosition * 10 }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}),
|
}),
|
||||||
[data.handleCount, data.handlePosition]
|
[handleCount]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={nodeStyles}>
|
<div style={nodeStyles}>
|
||||||
<Handle type="target" position={Position.Left} />
|
<Handle type="target" position={Position.Left} />
|
||||||
<div>output handle count: {data.handleCount}</div>
|
<div>output handle count: {handleCount}</div>
|
||||||
|
<button
|
||||||
|
onClick={() => {
|
||||||
|
setHandleCount((c) => c + 1);
|
||||||
|
updateNodeInternals(id);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
add handle
|
||||||
|
</button>
|
||||||
{handles}
|
{handles}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useCallback, CSSProperties, MouseEvent } from 'react';
|
import { useCallback, MouseEvent } from 'react';
|
||||||
|
|
||||||
import ReactFlow, {
|
import ReactFlow, {
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
@@ -8,26 +8,21 @@ import ReactFlow, {
|
|||||||
Node,
|
Node,
|
||||||
Connection,
|
Connection,
|
||||||
Edge,
|
Edge,
|
||||||
useUpdateNodeInternals,
|
|
||||||
Position,
|
Position,
|
||||||
useNodesState,
|
useNodesState,
|
||||||
useEdgesState,
|
useEdgesState,
|
||||||
} from 'react-flow-renderer';
|
} from 'react-flow-renderer';
|
||||||
import CustomNode from './CustomNode';
|
import CustomNode from './CustomNode';
|
||||||
|
|
||||||
const initialHandleCount = 1;
|
|
||||||
|
|
||||||
const initialNodes: Node[] = [
|
const initialNodes: Node[] = [
|
||||||
{
|
{
|
||||||
id: '1',
|
id: '1',
|
||||||
type: 'custom',
|
type: 'custom',
|
||||||
data: { label: 'Node 1', handleCount: initialHandleCount, handlePosition: 0 },
|
data: { label: 'Node 1' },
|
||||||
position: { x: 250, y: 5 },
|
position: { x: 250, y: 5 },
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const buttonWrapperStyles: CSSProperties = { position: 'absolute', right: 10, top: 10, zIndex: 10 };
|
|
||||||
|
|
||||||
const nodeTypes: NodeTypes = {
|
const nodeTypes: NodeTypes = {
|
||||||
custom: CustomNode,
|
custom: CustomNode,
|
||||||
};
|
};
|
||||||
@@ -40,7 +35,6 @@ const UpdateNodeInternalsFlow = () => {
|
|||||||
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
|
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
|
||||||
const onConnect = (params: Edge | Connection) => setEdges((els) => addEdge(params, els));
|
const onConnect = (params: Edge | Connection) => setEdges((els) => addEdge(params, els));
|
||||||
|
|
||||||
const updateNodeInternals = useUpdateNodeInternals();
|
|
||||||
const { project } = useReactFlow();
|
const { project } = useReactFlow();
|
||||||
|
|
||||||
const onPaneClick = useCallback(
|
const onPaneClick = useCallback(
|
||||||
@@ -56,25 +50,6 @@ const UpdateNodeInternalsFlow = () => {
|
|||||||
),
|
),
|
||||||
[project, setNodes]
|
[project, setNodes]
|
||||||
);
|
);
|
||||||
|
|
||||||
const toggleHandleCount = useCallback(() => {
|
|
||||||
setNodes((nds) =>
|
|
||||||
nds.map((node) => {
|
|
||||||
return { ...node, data: { ...node.data, handleCount: node.data?.handleCount === 1 ? 2 : 1 } };
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}, [setNodes]);
|
|
||||||
|
|
||||||
const toggleHandlePosition = useCallback(() => {
|
|
||||||
setNodes((nds) =>
|
|
||||||
nds.map((node) => {
|
|
||||||
return { ...node, data: { ...node.data, handlePosition: node.data?.handlePosition === 0 ? 1 : 0 } };
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}, [setNodes]);
|
|
||||||
|
|
||||||
const updateNode = useCallback(() => updateNodeInternals('1'), [updateNodeInternals]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReactFlow
|
<ReactFlow
|
||||||
nodes={nodes}
|
nodes={nodes}
|
||||||
@@ -84,13 +59,7 @@ const UpdateNodeInternalsFlow = () => {
|
|||||||
nodeTypes={nodeTypes}
|
nodeTypes={nodeTypes}
|
||||||
onConnect={onConnect}
|
onConnect={onConnect}
|
||||||
onPaneClick={onPaneClick}
|
onPaneClick={onPaneClick}
|
||||||
>
|
/>
|
||||||
<div style={buttonWrapperStyles}>
|
|
||||||
<button onClick={toggleHandleCount}>toggle handle count</button>
|
|
||||||
<button onClick={toggleHandlePosition}>toggle handle position</button>
|
|
||||||
<button onClick={updateNode}>update node internals</button>
|
|
||||||
</div>
|
|
||||||
</ReactFlow>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,15 +10,10 @@ function useUpdateNodeInternals(): UpdateNodeInternals {
|
|||||||
const updateNodeDimensions = useStore(selector);
|
const updateNodeDimensions = useStore(selector);
|
||||||
|
|
||||||
return useCallback<UpdateNodeInternals>((id: string) => {
|
return useCallback<UpdateNodeInternals>((id: string) => {
|
||||||
const { domNode } = store.getState();
|
const nodeElement = store.getState().domNode?.querySelector(`.react-flow__node[data-id="${id}"]`) as HTMLDivElement;
|
||||||
if (!domNode) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const nodeElement = domNode.querySelector(`.react-flow__node[data-id="${id}"]`) as HTMLDivElement;
|
|
||||||
|
|
||||||
if (nodeElement) {
|
if (nodeElement) {
|
||||||
updateNodeDimensions([{ id, nodeElement, forceUpdate: true }]);
|
requestAnimationFrame(() => updateNodeDimensions([{ id, nodeElement, forceUpdate: true }]));
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user