Fix: Resolve React Hook violation in ComparisonChart component

Root cause:
ComparisonChart was calling useSWR hooks dynamically inside a .map() loop,
which violates React's Rules of Hooks. When the traders array length changed
(e.g., from 0 to 2, or during initial load), the number of hook calls would
change between renders, triggering React Error #310.

Previous code:
```tsx
const traderHistories = traders.map((trader) => {
  return useSWR(`equity-history-${trader.trader_id}`, ...);  //  Dynamic hooks
});
```

The eslint-disable comment on line 24 was masking this critical issue.

Fix:
- Always call exactly 2 useSWR hooks (trader1, trader2) unconditionally
- Pass null as the key when trader doesn't exist (SWR handles this gracefully)
- Build traderHistories array from these fixed hooks
- Ensures same number of hooks called on every render

This follows React's Rules of Hooks:
 Only call hooks at the top level
 Don't call hooks inside loops, conditions, or nested functions
 Call hooks in the same order every render

Fixes: React Error #310 (Rendered more hooks than during previous render)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
PorunC
2025-10-29 20:49:22 +08:00
parent 8aa305290a
commit 48ab69befc

View File

@@ -19,14 +19,24 @@ interface ComparisonChartProps {
} }
export function ComparisonChart({ traders }: ComparisonChartProps) { export function ComparisonChart({ traders }: ComparisonChartProps) {
// 获取所有trader的历史数据 // 获取所有trader的历史数据 - 修复: 使用固定数量的Hook调用
const traderHistories = traders.map((trader) => { // 始终调用最多2个trader的useSWR即使实际trader数量不同
// eslint-disable-next-line react-hooks/rules-of-hooks const trader1 = traders[0];
return useSWR(`equity-history-${trader.trader_id}`, () => const trader2 = traders[1];
api.getEquityHistory(trader.trader_id),
{ refreshInterval: 10000 } const history1 = useSWR(
); trader1 ? `equity-history-${trader1.trader_id}` : null,
}); trader1 ? () => api.getEquityHistory(trader1.trader_id) : null,
{ refreshInterval: 10000 }
);
const history2 = useSWR(
trader2 ? `equity-history-${trader2.trader_id}` : null,
trader2 ? () => api.getEquityHistory(trader2.trader_id) : null,
{ refreshInterval: 10000 }
);
const traderHistories = [history1, history2].slice(0, traders.length);
// 使用useMemo自动处理数据合并直接使用data对象作为依赖 // 使用useMemo自动处理数据合并直接使用data对象作为依赖
const combinedData = useMemo(() => { const combinedData = useMemo(() => {