fix(react): ReactFlow comp ref type

This commit is contained in:
moklick
2024-03-04 12:01:26 +01:00
parent 82f40b4a67
commit e972656c3d
5 changed files with 188 additions and 178 deletions
@@ -1,4 +1,4 @@
import { useState, useEffect, MouseEvent, ChangeEvent, useCallback } from 'react'; import { useState, useEffect, MouseEvent, ChangeEvent, useCallback, useRef } from 'react';
import { import {
ReactFlow, ReactFlow,
MiniMap, MiniMap,
@@ -45,6 +45,7 @@ const nodeTypes = {
}; };
const CustomNodeFlow = () => { const CustomNodeFlow = () => {
const ref = useRef(null);
const [nodes, setNodes] = useState<MyNode[]>([]); const [nodes, setNodes] = useState<MyNode[]>([]);
const onNodesChange: OnNodesChange<MyNode> = useCallback( const onNodesChange: OnNodesChange<MyNode> = useCallback(
(changes) => (changes) =>
@@ -165,6 +166,7 @@ const CustomNodeFlow = () => {
minZoom={0.3} minZoom={0.3}
maxZoom={2} maxZoom={2}
onBeforeDelete={onBeforeDelete} onBeforeDelete={onBeforeDelete}
ref={ref}
> >
<MiniMap<MyNode> <MiniMap<MyNode>
nodeStrokeColor={(n: MyNode): string => { nodeStrokeColor={(n: MyNode): string => {
+13 -10
View File
@@ -3,7 +3,14 @@
* The user can then drag the connection to another handle or node. When the user releases the mouse, we check if the * 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. * connection is valid and if so, we call the onConnect callback.
*/ */
import { memo, HTMLAttributes, forwardRef, MouseEvent as ReactMouseEvent, TouchEvent as ReactTouchEvent } from 'react'; import {
memo,
HTMLAttributes,
forwardRef,
MouseEvent as ReactMouseEvent,
TouchEvent as ReactTouchEvent,
ForwardedRef,
} from 'react';
import cc from 'classcat'; import cc from 'classcat';
import { shallow } from 'zustand/shallow'; import { shallow } from 'zustand/shallow';
import { import {
@@ -58,8 +65,7 @@ const connectingSelector =
}; };
}; };
const HandleComponent = forwardRef<HTMLDivElement, HandleComponentProps>( function HandleComponent(
(
{ {
type = 'source', type = 'source',
position = Position.Top, position = Position.Top,
@@ -74,9 +80,9 @@ const HandleComponent = forwardRef<HTMLDivElement, HandleComponentProps>(
onMouseDown, onMouseDown,
onTouchStart, onTouchStart,
...rest ...rest
}, }: HandleComponentProps,
ref ref: ForwardedRef<HTMLDivElement>
) => { ) {
const handleId = id || null; const handleId = id || null;
const isTarget = type === 'target'; const isTarget = type === 'target';
const store = useStoreApi(); const store = useStoreApi();
@@ -237,11 +243,8 @@ const HandleComponent = forwardRef<HTMLDivElement, HandleComponentProps>(
</div> </div>
); );
} }
);
HandleComponent.displayName = 'Handle';
/** /**
* The Handle component is the part of a node that can be used to connect nodes. * The Handle component is the part of a node that can be used to connect nodes.
*/ */
export const Handle = memo(HandleComponent); export const Handle = memo(forwardRef(HandleComponent));
@@ -9,7 +9,7 @@ import { StoreUpdater } from '../../components/StoreUpdater';
import { useColorModeClass } from '../../hooks/useColorModeClass'; import { useColorModeClass } from '../../hooks/useColorModeClass';
import { GraphView } from '../GraphView'; import { GraphView } from '../GraphView';
import { Wrapper } from './Wrapper'; import { Wrapper } from './Wrapper';
import type { Edge, Node, ReactFlowProps, ReactFlowRefType } from '../../types'; import type { Edge, Node, ReactFlowProps } from '../../types';
import { defaultViewport as initViewport, defaultNodeOrigin } from './init-values'; import { defaultViewport as initViewport, defaultNodeOrigin } from './init-values';
const wrapperStyle: CSSProperties = { const wrapperStyle: CSSProperties = {
@@ -142,7 +142,7 @@ function ReactFlow<NodeType extends Node = Node, EdgeType extends Edge = Edge>(
debug, debug,
...rest ...rest
}: ReactFlowProps<NodeType, EdgeType>, }: ReactFlowProps<NodeType, EdgeType>,
ref: ForwardedRef<ReactFlowRefType> ref: ForwardedRef<HTMLDivElement>
) { ) {
const rfId = id || '1'; const rfId = id || '1';
const colorModeClassName = useColorModeClass(colorMode); const colorModeClassName = useColorModeClass(colorMode);
@@ -286,4 +286,4 @@ function ReactFlow<NodeType extends Node = Node, EdgeType extends Edge = Edge>(
); );
} }
export default forwardRef(ReactFlow) as typeof ReactFlow; export default forwardRef(ReactFlow);
@@ -509,5 +509,3 @@ export interface ReactFlowProps<NodeType extends Node = Node, EdgeType extends E
*/ */
debug?: boolean; debug?: boolean;
} }
export type ReactFlowRefType = HTMLDivElement;
+8 -1
View File
@@ -1,3 +1,4 @@
import { ComponentType } from 'react';
import { import {
FitViewParamsBase, FitViewParamsBase,
FitViewOptionsBase, FitViewOptionsBase,
@@ -15,7 +16,13 @@ import {
} from '@xyflow/system'; } from '@xyflow/system';
import type { NodeChange, EdgeChange, Node, Edge, ReactFlowInstance, EdgeProps } from '.'; import type { NodeChange, EdgeChange, Node, Edge, ReactFlowInstance, EdgeProps } from '.';
import { ComponentType } from 'react';
// this is needed, to use generics + forwardRef
declare module 'react' {
function forwardRef<T, P>(
render: (props: P, ref: React.Ref<T>) => React.ReactNode | null
): (props: P & React.RefAttributes<T>) => React.ReactNode | null;
}
export type OnNodesChange<NodeType extends Node = Node> = (changes: NodeChange<NodeType>[]) => void; export type OnNodesChange<NodeType extends Node = Node> = (changes: NodeChange<NodeType>[]) => void;
export type OnEdgesChange<EdgeType extends Edge = Edge> = (changes: EdgeChange<EdgeType>[]) => void; export type OnEdgesChange<EdgeType extends Edge = Edge> = (changes: EdgeChange<EdgeType>[]) => void;