Skip to content

Commit d47ada4

Browse files
author
ChidcGithub
committed
fix: resolve React hooks exhaustive-deps warning in ProjectVisualization
- Move getCytoscapeStyles outside component to avoid dependency issue - Add themeRef to track theme without triggering re-initialization - Remove getCytoscapeStyles from useEffect dependency array
1 parent 0a8b75b commit d47ada4

1 file changed

Lines changed: 94 additions & 84 deletions

File tree

frontend/src/components/ProjectVisualization.js

Lines changed: 94 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,106 @@ import './components.css';
1010
cytoscape.use(dagre);
1111
cytoscape.use(fcose);
1212

13+
/**
14+
* Get Cytoscape styles based on theme
15+
* @param {boolean} isDark - Whether to use dark theme
16+
* @returns {Array} Cytoscape style array
17+
*/
18+
function getCytoscapeStyles(isDark) {
19+
return [
20+
// Regular module nodes - rectangle
21+
{
22+
selector: 'node[type="file"]',
23+
style: {
24+
'shape': 'roundrectangle',
25+
'background-color': isDark ? '#1f2937' : '#ffffff',
26+
'label': 'data(label)',
27+
'text-valign': 'center',
28+
'text-halign': 'center',
29+
'font-size': '11px',
30+
'font-family': 'Inter, sans-serif',
31+
'color': isDark ? '#e5e7eb' : '#374151',
32+
'width': 80,
33+
'height': 40,
34+
'text-wrap': 'wrap',
35+
'text-max-width': 70,
36+
'border-width': 2,
37+
'border-color': isDark ? '#4b5563' : '#374151',
38+
'corner-radius': 4,
39+
},
40+
},
41+
// Circular dependency nodes - diamond
42+
{
43+
selector: 'node[type="circular"]',
44+
style: {
45+
'shape': 'diamond',
46+
'background-color': isDark ? '#7f1d1d' : '#fecaca',
47+
'label': 'data(label)',
48+
'text-valign': 'center',
49+
'text-halign': 'center',
50+
'font-size': '11px',
51+
'font-family': 'Inter, sans-serif',
52+
'color': isDark ? '#fca5a5' : '#991b1b',
53+
'width': 70,
54+
'height': 70,
55+
'text-wrap': 'wrap',
56+
'text-max-width': 60,
57+
'border-width': 2,
58+
'border-color': '#dc2626',
59+
},
60+
},
61+
// Selected state
62+
{
63+
selector: 'node:selected',
64+
style: {
65+
'border-width': 3,
66+
'border-color': isDark ? '#60a5fa' : '#2563eb',
67+
},
68+
},
69+
// Regular import edges - solid line
70+
{
71+
selector: 'edge[type="import"]',
72+
style: {
73+
'width': 1.5,
74+
'line-color': isDark ? '#6b7280' : '#9ca3af',
75+
'target-arrow-color': isDark ? '#6b7280' : '#9ca3af',
76+
'target-arrow-shape': 'triangle',
77+
'curve-style': 'bezier',
78+
'arrow-scale': 0.6,
79+
'line-style': 'solid',
80+
},
81+
},
82+
// Circular dependency edges - dashed line
83+
{
84+
selector: 'edge[type="circular"]',
85+
style: {
86+
'width': 2,
87+
'line-color': '#dc2626',
88+
'target-arrow-color': '#dc2626',
89+
'target-arrow-shape': 'triangle',
90+
'curve-style': 'bezier',
91+
'arrow-scale': 0.7,
92+
'line-style': 'dashed',
93+
},
94+
},
95+
];
96+
}
97+
1398
/**
1499
* Project Dependency Visualization Component
15100
* Uses Cytoscape.js to display project file dependency graphs
16101
*/
17102
function ProjectVisualization({ projectResult, theme, viewMode = '2d' }) {
18103
const containerRef = useRef(null);
19104
const cyRef = useRef(null);
105+
const themeRef = useRef(theme);
20106
const [selectedNode, setSelectedNode] = useState(null);
21107

108+
// Keep themeRef in sync with theme prop
109+
useEffect(() => {
110+
themeRef.current = theme;
111+
}, [theme]);
112+
22113
// Process dependency data into graph data
23114
const graphData = useMemo(() => {
24115
if (!projectResult) return { nodes: [], edges: [] };
@@ -108,7 +199,7 @@ function ProjectVisualization({ projectResult, theme, viewMode = '2d' }) {
108199
container: container,
109200
elements: [...graphData.nodes, ...graphData.edges],
110201

111-
style: getCytoscapeStyles(theme),
202+
style: getCytoscapeStyles(themeRef.current === 'dark'),
112203

113204
layout: {
114205
name: 'fcose',
@@ -144,95 +235,14 @@ function ProjectVisualization({ projectResult, theme, viewMode = '2d' }) {
144235
logger.error('Cytoscape initialization error', { error: error.message });
145236
return false;
146237
}
147-
}, [graphData]); // Remove theme dependency to avoid rebuilding on theme change
148-
149-
// Get Cytoscape styles based on theme
150-
const getCytoscapeStyles = useCallback((isDark) => {
151-
return [
152-
// Regular module nodes - rectangle
153-
{
154-
selector: 'node[type="file"]',
155-
style: {
156-
'shape': 'roundrectangle',
157-
'background-color': isDark ? '#1f2937' : '#ffffff',
158-
'label': 'data(label)',
159-
'text-valign': 'center',
160-
'text-halign': 'center',
161-
'font-size': '11px',
162-
'font-family': 'Inter, sans-serif',
163-
'color': isDark ? '#e5e7eb' : '#374151',
164-
'width': 80,
165-
'height': 40,
166-
'text-wrap': 'wrap',
167-
'text-max-width': 70,
168-
'border-width': 2,
169-
'border-color': isDark ? '#4b5563' : '#374151',
170-
'corner-radius': 4,
171-
},
172-
},
173-
// Circular dependency nodes - diamond
174-
{
175-
selector: 'node[type="circular"]',
176-
style: {
177-
'shape': 'diamond',
178-
'background-color': isDark ? '#7f1d1d' : '#fecaca',
179-
'label': 'data(label)',
180-
'text-valign': 'center',
181-
'text-halign': 'center',
182-
'font-size': '11px',
183-
'font-family': 'Inter, sans-serif',
184-
'color': isDark ? '#fca5a5' : '#991b1b',
185-
'width': 70,
186-
'height': 70,
187-
'text-wrap': 'wrap',
188-
'text-max-width': 60,
189-
'border-width': 2,
190-
'border-color': '#dc2626',
191-
},
192-
},
193-
// Selected state
194-
{
195-
selector: 'node:selected',
196-
style: {
197-
'border-width': 3,
198-
'border-color': isDark ? '#60a5fa' : '#2563eb',
199-
},
200-
},
201-
// Regular import edges - solid line
202-
{
203-
selector: 'edge[type="import"]',
204-
style: {
205-
'width': 1.5,
206-
'line-color': isDark ? '#6b7280' : '#9ca3af',
207-
'target-arrow-color': isDark ? '#6b7280' : '#9ca3af',
208-
'target-arrow-shape': 'triangle',
209-
'curve-style': 'bezier',
210-
'arrow-scale': 0.6,
211-
'line-style': 'solid',
212-
},
213-
},
214-
// Circular dependency edges - dashed line
215-
{
216-
selector: 'edge[type="circular"]',
217-
style: {
218-
'width': 2,
219-
'line-color': '#dc2626',
220-
'target-arrow-color': '#dc2626',
221-
'target-arrow-shape': 'triangle',
222-
'curve-style': 'bezier',
223-
'arrow-scale': 0.7,
224-
'line-style': 'dashed',
225-
},
226-
},
227-
];
228-
}, []);
238+
}, [graphData]);
229239

230240
// Update styles when theme changes (without rebuilding the entire graph)
231241
useEffect(() => {
232242
if (cyRef.current) {
233243
cyRef.current.style(getCytoscapeStyles(theme === 'dark'));
234244
}
235-
}, [theme, getCytoscapeStyles]);
245+
}, [theme]);
236246

237247
// Delayed initialization to ensure container dimensions are correct
238248
useEffect(() => {

0 commit comments

Comments
 (0)