refactor(nodeTypes/edgeTypes): show warning when not memoized closes #1620

This commit is contained in:
moklick
2022-02-22 18:33:59 +01:00
parent a45af5f0f8
commit 6630935d9e
17 changed files with 82 additions and 40 deletions
+1
View File
@@ -27,6 +27,7 @@ const initBgColor = '#1A192B';
const connectionLineStyle = { stroke: '#fff' }; const connectionLineStyle = { stroke: '#fff' };
const snapGrid: SnapGrid = [16, 16]; const snapGrid: SnapGrid = [16, 16];
const nodeTypes = { const nodeTypes = {
selectorNode: ColorSelectorNode, selectorNode: ColorSelectorNode,
}; };
+2 -2
View File
@@ -6,7 +6,7 @@ import ReactFlow, {
Controls, Controls,
Background, Background,
ReactFlowInstance, ReactFlowInstance,
EdgeTypesType, EdgeTypes,
Connection, Connection,
Edge, Edge,
MarkerType, MarkerType,
@@ -102,7 +102,7 @@ const initialEdges: Edge[] = [
}, },
]; ];
const edgeTypes: EdgeTypesType = { const edgeTypes: EdgeTypes = {
custom: CustomEdge, custom: CustomEdge,
custom2: CustomEdge2, custom2: CustomEdge2,
}; };
+2 -2
View File
@@ -4,7 +4,7 @@ import ReactFlow, {
addEdge, addEdge,
Background, Background,
ReactFlowInstance, ReactFlowInstance,
EdgeTypesType, EdgeTypes,
Connection, Connection,
useNodesState, useNodesState,
useEdgesState, useEdgesState,
@@ -20,7 +20,7 @@ const onInit = (reactFlowInstance: ReactFlowInstance) => reactFlowInstance.fitVi
const { nodes: initialNodes, edges: initialEdges } = createElements(); const { nodes: initialNodes, edges: initialEdges } = createElements();
const edgeTypes: EdgeTypesType = { const edgeTypes: EdgeTypes = {
floating: FloatingEdge, floating: FloatingEdge,
}; };
+2 -2
View File
@@ -7,7 +7,7 @@ import ReactFlow, {
Connection, Connection,
Edge, Edge,
NodeProps, NodeProps,
NodeTypesType, NodeTypes,
useNodesState, useNodesState,
useEdgesState, useEdgesState,
} from 'react-flow-renderer'; } from 'react-flow-renderer';
@@ -43,7 +43,7 @@ const NodeB: FC<NodeProps> = () => {
}; };
type NodeTypesObject = { type NodeTypesObject = {
[key: string]: NodeTypesType; [key: string]: NodeTypes;
}; };
const nodeTypesObjects: NodeTypesObject = { const nodeTypesObjects: NodeTypesObject = {
+2 -2
View File
@@ -2,7 +2,7 @@ import { useCallback } from 'react';
import ReactFlow, { import ReactFlow, {
useReactFlow, useReactFlow,
NodeTypesType, NodeTypes,
addEdge, addEdge,
ReactFlowProvider, ReactFlowProvider,
Node, Node,
@@ -172,7 +172,7 @@ const initialEdges: Edge[] = [
}, },
]; ];
const nodeTypes: NodeTypesType = { const nodeTypes: NodeTypes = {
custom: CustomNode, custom: CustomNode,
}; };
+2 -2
View File
@@ -1,7 +1,7 @@
import { useCallback, CSSProperties } from 'react'; import { useCallback, CSSProperties } from 'react';
import ReactFlow, { import ReactFlow, {
NodeTypesType, NodeTypes,
addEdge, addEdge,
useReactFlow, useReactFlow,
ReactFlowProvider, ReactFlowProvider,
@@ -28,7 +28,7 @@ const initialNodes: Node[] = [
const buttonWrapperStyles: CSSProperties = { position: 'absolute', right: 10, top: 10, zIndex: 10 }; const buttonWrapperStyles: CSSProperties = { position: 'absolute', right: 10, top: 10, zIndex: 10 };
const nodeTypes: NodeTypesType = { const nodeTypes: NodeTypes = {
custom: CustomNode, custom: CustomNode,
}; };
+2 -2
View File
@@ -8,7 +8,7 @@ import ReactFlow, {
Edge, Edge,
OnConnectStartParams, OnConnectStartParams,
NodeProps, NodeProps,
NodeTypesType, NodeTypes,
useNodesState, useNodesState,
useEdgesState, useEdgesState,
} from 'react-flow-renderer'; } from 'react-flow-renderer';
@@ -43,7 +43,7 @@ const CustomNode: FC<NodeProps> = ({ id }) => (
</> </>
); );
const nodeTypes: NodeTypesType = { const nodeTypes: NodeTypes = {
custominput: CustomInput, custominput: CustomInput,
customnode: CustomNode, customnode: CustomNode,
}; };
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "react-flow-renderer", "name": "react-flow-renderer",
"version": "10.0.0-next.41", "version": "10.0.0-next.42",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "react-flow-renderer", "name": "react-flow-renderer",
"version": "10.0.0-next.41", "version": "10.0.0-next.42",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/runtime": "^7.16.7", "@babel/runtime": "^7.16.7",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "react-flow-renderer", "name": "react-flow-renderer",
"version": "10.0.0-next.41", "version": "10.0.0-next.42",
"engines": { "engines": {
"node": ">=12" "node": ">=12"
}, },
+7 -5
View File
@@ -5,7 +5,7 @@ import wrapEdge from '../../components/Edges/wrapEdge';
import { rectToBox } from '../../utils'; import { rectToBox } from '../../utils';
import { import {
EdgeTypesType, EdgeTypes,
EdgeProps, EdgeProps,
HandleElement, HandleElement,
Position, Position,
@@ -16,16 +16,18 @@ import {
NodeHandleBounds, NodeHandleBounds,
} from '../../types'; } from '../../types';
export function createEdgeTypes(edgeTypes: EdgeTypesType): EdgeTypesType { export type CreateEdgeTypes = (edgeTypes: EdgeTypes) => EdgeTypes;
const standardTypes: EdgeTypesType = {
export function createEdgeTypes(edgeTypes: EdgeTypes): EdgeTypes {
const standardTypes: EdgeTypes = {
default: wrapEdge((edgeTypes.default || BezierEdge) as ComponentType<EdgeProps>), default: wrapEdge((edgeTypes.default || BezierEdge) as ComponentType<EdgeProps>),
straight: wrapEdge((edgeTypes.bezier || StraightEdge) as ComponentType<EdgeProps>), straight: wrapEdge((edgeTypes.bezier || StraightEdge) as ComponentType<EdgeProps>),
step: wrapEdge((edgeTypes.step || StepEdge) as ComponentType<EdgeProps>), step: wrapEdge((edgeTypes.step || StepEdge) as ComponentType<EdgeProps>),
smoothstep: wrapEdge((edgeTypes.step || SmoothStepEdge) as ComponentType<EdgeProps>), smoothstep: wrapEdge((edgeTypes.step || SmoothStepEdge) as ComponentType<EdgeProps>),
}; };
const wrappedTypes = {} as EdgeTypesType; const wrappedTypes = {} as EdgeTypes;
const specialTypes: EdgeTypesType = Object.keys(edgeTypes) const specialTypes: EdgeTypes = Object.keys(edgeTypes)
.filter((k) => !['default', 'bezier'].includes(k)) .filter((k) => !['default', 'bezier'].includes(k))
.reduce((res, key) => { .reduce((res, key) => {
res[key] = wrapEdge((edgeTypes[key] || BezierEdge) as ComponentType<EdgeProps>); res[key] = wrapEdge((edgeTypes[key] || BezierEdge) as ComponentType<EdgeProps>);
+3 -3
View File
@@ -5,11 +5,11 @@ import NodeRenderer from '../NodeRenderer';
import EdgeRenderer from '../EdgeRenderer'; import EdgeRenderer from '../EdgeRenderer';
import Viewport from '../Viewport'; import Viewport from '../Viewport';
import useOnInitHandler from '../../hooks/useOnInitHandler'; import useOnInitHandler from '../../hooks/useOnInitHandler';
import { NodeTypesType, EdgeTypesType, ConnectionLineType, KeyCode, ReactFlowProps } from '../../types'; import { NodeTypes, EdgeTypes, ConnectionLineType, KeyCode, ReactFlowProps } from '../../types';
export interface GraphViewProps extends Omit<ReactFlowProps, 'onSelectionChange' | 'nodes' | 'edges'> { export interface GraphViewProps extends Omit<ReactFlowProps, 'onSelectionChange' | 'nodes' | 'edges'> {
nodeTypes: NodeTypesType; nodeTypes: NodeTypes;
edgeTypes: EdgeTypesType; edgeTypes: EdgeTypes;
selectionKeyCode: KeyCode; selectionKeyCode: KeyCode;
deleteKeyCode: KeyCode; deleteKeyCode: KeyCode;
multiSelectionKeyCode: KeyCode; multiSelectionKeyCode: KeyCode;
+2 -2
View File
@@ -3,10 +3,10 @@ import shallow from 'zustand/shallow';
import useVisibleNodes from '../../hooks/useVisibleNodes'; import useVisibleNodes from '../../hooks/useVisibleNodes';
import { useStore } from '../../store'; import { useStore } from '../../store';
import { Node, NodeTypesType, Position, ReactFlowState, WrapNodeProps } from '../../types'; import { Node, NodeTypes, Position, ReactFlowState, WrapNodeProps } from '../../types';
interface NodeRendererProps { interface NodeRendererProps {
nodeTypes: NodeTypesType; nodeTypes: NodeTypes;
selectNodesOnDrag: boolean; selectNodesOnDrag: boolean;
onNodeClick?: (event: MouseEvent, element: Node) => void; onNodeClick?: (event: MouseEvent, element: Node) => void;
onNodeDoubleClick?: (event: MouseEvent, element: Node) => void; onNodeDoubleClick?: (event: MouseEvent, element: Node) => void;
+7 -5
View File
@@ -5,18 +5,20 @@ import InputNode from '../../components/Nodes/InputNode';
import OutputNode from '../../components/Nodes/OutputNode'; import OutputNode from '../../components/Nodes/OutputNode';
import GroupNode from '../../components/Nodes/GroupNode'; import GroupNode from '../../components/Nodes/GroupNode';
import wrapNode from '../../components/Nodes/wrapNode'; import wrapNode from '../../components/Nodes/wrapNode';
import { NodeTypesType, NodeProps } from '../../types'; import { NodeTypes, NodeProps } from '../../types';
export function createNodeTypes(nodeTypes: NodeTypesType): NodeTypesType { export type CreateNodeTypes = (nodeTypes: NodeTypes) => NodeTypes;
const standardTypes: NodeTypesType = {
export function createNodeTypes(nodeTypes: NodeTypes): NodeTypes {
const standardTypes: NodeTypes = {
input: wrapNode((nodeTypes.input || InputNode) as ComponentType<NodeProps>), input: wrapNode((nodeTypes.input || InputNode) as ComponentType<NodeProps>),
default: wrapNode((nodeTypes.default || DefaultNode) as ComponentType<NodeProps>), default: wrapNode((nodeTypes.default || DefaultNode) as ComponentType<NodeProps>),
output: wrapNode((nodeTypes.output || OutputNode) as ComponentType<NodeProps>), output: wrapNode((nodeTypes.output || OutputNode) as ComponentType<NodeProps>),
group: wrapNode((nodeTypes.group || GroupNode) as ComponentType<NodeProps>), group: wrapNode((nodeTypes.group || GroupNode) as ComponentType<NodeProps>),
}; };
const wrappedTypes = {} as NodeTypesType; const wrappedTypes = {} as NodeTypes;
const specialTypes: NodeTypesType = Object.keys(nodeTypes) const specialTypes: NodeTypes = Object.keys(nodeTypes)
.filter((k) => !['input', 'default', 'output', 'group'].includes(k)) .filter((k) => !['input', 'default', 'output', 'group'].includes(k))
.reduce((res, key) => { .reduce((res, key) => {
res[key] = wrapNode((nodeTypes[key] || DefaultNode) as ComponentType<NodeProps>); res[key] = wrapNode((nodeTypes[key] || DefaultNode) as ComponentType<NodeProps>);
+13 -4
View File
@@ -1,4 +1,4 @@
import React, { useMemo, forwardRef } from 'react'; import React, { forwardRef } from 'react';
import cc from 'classcat'; import cc from 'classcat';
import GraphView from '../GraphView'; import GraphView from '../GraphView';
@@ -13,10 +13,19 @@ import Attribution from '../../components/Attribution';
import { createEdgeTypes } from '../EdgeRenderer/utils'; import { createEdgeTypes } from '../EdgeRenderer/utils';
import Wrapper from './Wrapper'; import Wrapper from './Wrapper';
import { ConnectionMode, ConnectionLineType, PanOnScrollMode, ReactFlowProps, ReactFlowRefType } from '../../types'; import {
ConnectionMode,
ConnectionLineType,
PanOnScrollMode,
ReactFlowProps,
ReactFlowRefType,
NodeTypes,
EdgeTypes,
} from '../../types';
import '../../style.css'; import '../../style.css';
import '../../theme-default.css'; import '../../theme-default.css';
import { useNodeOrEdgeTypes } from './utils';
const defaultNodeTypes = { const defaultNodeTypes = {
input: InputNode, input: InputNode,
@@ -127,8 +136,8 @@ const ReactFlow = forwardRef<ReactFlowRefType, ReactFlowProps>(
}, },
ref ref
) => { ) => {
const nodeTypesParsed = useMemo(() => createNodeTypes(nodeTypes), [nodeTypes]); const nodeTypesParsed = useNodeOrEdgeTypes(nodeTypes, createNodeTypes) as NodeTypes;
const edgeTypesParsed = useMemo(() => createEdgeTypes(edgeTypes), [edgeTypes]); const edgeTypesParsed = useNodeOrEdgeTypes(edgeTypes, createEdgeTypes) as EdgeTypes;
const reactFlowClasses = cc(['react-flow', className]); const reactFlowClasses = cc(['react-flow', className]);
return ( return (
+28
View File
@@ -0,0 +1,28 @@
import { useMemo, useRef } from 'react';
import shallow from 'zustand/shallow';
import { EdgeTypes, NodeTypes } from '../../types';
import { CreateEdgeTypes } from '../EdgeRenderer/utils';
import { CreateNodeTypes } from '../NodeRenderer/utils';
export function useNodeOrEdgeTypes(nodeOrEdgeTypes: NodeTypes, createTypes: CreateNodeTypes): NodeTypes;
export function useNodeOrEdgeTypes(nodeOrEdgeTypes: EdgeTypes, createTypes: CreateEdgeTypes): EdgeTypes;
export function useNodeOrEdgeTypes(nodeOrEdgeTypes: any, createTypes: any): any {
const typesKeysRef = useRef<string[] | null>(null);
const typesParsed = useMemo(() => {
if (process.env.NODE_ENV === 'development') {
const typeKeys = Object.keys(nodeOrEdgeTypes);
if (shallow(typesKeysRef.current, typeKeys)) {
console.warn(
"React Flow: It looks like that you created a new nodeTypes or edgeTypes object. If this wasn't on purpose please define the nodeTypes/edgeTypes outside of the component or memoize them."
);
}
typesKeysRef.current = typeKeys;
}
return createTypes(nodeOrEdgeTypes);
}, [nodeOrEdgeTypes]);
return typesParsed;
}
+4 -4
View File
@@ -2,8 +2,8 @@ import React, { CSSProperties, HTMLAttributes, MouseEvent as ReactMouseEvent, Wh
import { import {
OnSelectionChangeFunc, OnSelectionChangeFunc,
NodeTypesType, NodeTypes,
EdgeTypesType, EdgeTypes,
Node, Node,
Edge, Edge,
ConnectionMode, ConnectionMode,
@@ -68,8 +68,8 @@ export interface ReactFlowProps extends HTMLAttributes<HTMLDivElement> {
onPaneScroll?: (event?: WheelEvent) => void; onPaneScroll?: (event?: WheelEvent) => void;
onPaneClick?: (event: ReactMouseEvent) => void; onPaneClick?: (event: ReactMouseEvent) => void;
onPaneContextMenu?: (event: ReactMouseEvent) => void; onPaneContextMenu?: (event: ReactMouseEvent) => void;
nodeTypes?: NodeTypesType; nodeTypes?: NodeTypes;
edgeTypes?: EdgeTypesType; edgeTypes?: EdgeTypes;
connectionMode?: ConnectionMode; connectionMode?: ConnectionMode;
connectionLineType?: ConnectionLineType; connectionLineType?: ConnectionLineType;
connectionLineStyle?: CSSProperties; connectionLineStyle?: CSSProperties;
+2 -2
View File
@@ -9,8 +9,8 @@ import { HandleType, StartHandle } from './handles';
import { DefaultEdgeOptions } from '.'; import { DefaultEdgeOptions } from '.';
import { ReactFlowInstance } from './instance'; import { ReactFlowInstance } from './instance';
export type NodeTypesType = { [key: string]: ReactNode }; export type NodeTypes = { [key: string]: ReactNode };
export type EdgeTypesType = NodeTypesType; export type EdgeTypes = NodeTypes;
export type FitView = (fitViewOptions?: FitViewOptions) => void; export type FitView = (fitViewOptions?: FitViewOptions) => void;