mirror of
https://github.com/OFFIS-ESC/constellation-analyzer
synced 2026-03-13 12:08:46 +00:00
Fix store subscription storm with shallow equality
Critical Performance Issue: - Every CustomNode and CustomEdge subscribed to entire store arrays - 100 nodes × 2 subscriptions + 200 edges × 3 subscriptions = 800 listeners - ANY change to nodeTypes/labels/edgeTypes triggered ALL components to re-render - Example: Changing one node type color → 300 components re-render Solution: - Add shallow equality checking to all store subscriptions - Components now only re-render when array CONTENTS change - Prevents cascade re-renders from reference changes Files Modified: - CustomNode.tsx: nodeTypes, labels with shallow - CustomEdge.tsx: edgeTypes, labels, nodeTypes with shallow Expected Impact: - Eliminates unnecessary re-renders during viewport changes - Should dramatically improve responsiveness during pan/zoom - Reduces re-render churn when editing types/labels Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
de87be5f66
commit
8feccb6a48
2 changed files with 7 additions and 5 deletions
|
|
@ -6,6 +6,7 @@ import {
|
|||
useInternalNode,
|
||||
} from '@xyflow/react';
|
||||
import { useGraphStore } from '../../stores/graphStore';
|
||||
import { shallow } from 'zustand/shallow';
|
||||
import type { Relation } from '../../types';
|
||||
import LabelBadge from '../Common/LabelBadge';
|
||||
import { getFloatingEdgeParams } from '../../utils/edgeUtils';
|
||||
|
|
@ -35,9 +36,9 @@ const CustomEdge = ({
|
|||
data,
|
||||
selected,
|
||||
}: EdgeProps<Relation>) => {
|
||||
const edgeTypes = useGraphStore((state) => state.edgeTypes);
|
||||
const labels = useGraphStore((state) => state.labels);
|
||||
const nodeTypes = useGraphStore((state) => state.nodeTypes);
|
||||
const edgeTypes = useGraphStore((state) => state.edgeTypes, shallow);
|
||||
const labels = useGraphStore((state) => state.labels, shallow);
|
||||
const nodeTypes = useGraphStore((state) => state.nodeTypes, shallow);
|
||||
|
||||
// Get active filters based on mode (editing vs presentation)
|
||||
const filters = useActiveFilters();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { memo, useMemo } from "react";
|
||||
import { Handle, Position, NodeProps } from "@xyflow/react";
|
||||
import { useGraphStore } from "../../stores/graphStore";
|
||||
import { shallow } from "zustand/shallow";
|
||||
import {
|
||||
getContrastColor,
|
||||
adjustColorBrightness,
|
||||
|
|
@ -26,8 +27,8 @@ import {
|
|||
* Usage: Automatically rendered by React Flow for nodes with type='custom'
|
||||
*/
|
||||
const CustomNode = ({ data, selected }: NodeProps<Actor>) => {
|
||||
const nodeTypes = useGraphStore((state) => state.nodeTypes);
|
||||
const labels = useGraphStore((state) => state.labels);
|
||||
const nodeTypes = useGraphStore((state) => state.nodeTypes, shallow);
|
||||
const labels = useGraphStore((state) => state.labels, shallow);
|
||||
|
||||
// Get active filters based on mode (editing vs presentation)
|
||||
const filters = useActiveFilters();
|
||||
|
|
|
|||
Loading…
Reference in a new issue