Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
Sync from GitHub via hub-sync
Browse files- src/components/data-recharts.tsx +30 -13
src/components/data-recharts.tsx
CHANGED
|
@@ -1,6 +1,12 @@
|
|
| 1 |
"use client";
|
| 2 |
|
| 3 |
-
import React, {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
import { useTime } from "../context/time-context";
|
| 5 |
import {
|
| 6 |
LineChart,
|
|
@@ -191,21 +197,32 @@ const SingleDataGraph = React.memo(
|
|
| 191 |
);
|
| 192 |
|
| 193 |
// Flatten all rows for recharts
|
| 194 |
-
const chartData = useMemo(
|
| 195 |
-
() => data.map((row) => flattenRow(row)),
|
| 196 |
-
[data, flattenRow],
|
| 197 |
-
);
|
| 198 |
-
const [dataKeys, setDataKeys] = useState<string[]>([]);
|
| 199 |
-
const [visibleKeys, setVisibleKeys] = useState<string[]>([]);
|
| 200 |
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
|
|
|
|
|
|
| 207 |
}, [chartData]);
|
| 208 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 209 |
const { groups, singles, groupColorMap } = useMemo(() => {
|
| 210 |
const grouped: Record<string, string[]> = {};
|
| 211 |
const singleList: string[] = [];
|
|
|
|
| 1 |
"use client";
|
| 2 |
|
| 3 |
+
import React, {
|
| 4 |
+
useCallback,
|
| 5 |
+
useEffect,
|
| 6 |
+
useMemo,
|
| 7 |
+
useRef,
|
| 8 |
+
useState,
|
| 9 |
+
} from "react";
|
| 10 |
import { useTime } from "../context/time-context";
|
| 11 |
import {
|
| 12 |
LineChart,
|
|
|
|
| 197 |
);
|
| 198 |
|
| 199 |
// Flatten all rows for recharts
|
| 200 |
+
const chartData = useMemo(() => data.map((row) => flattenRow(row)), [data]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 201 |
|
| 202 |
+
// dataKeys is purely derived from chartData — compute it during render,
|
| 203 |
+
// not via a useState + useEffect that would force an extra render and
|
| 204 |
+
// briefly leak the previous chart's keys after `data` changes.
|
| 205 |
+
// Vercel rule: rerender-derived-state-no-effect.
|
| 206 |
+
const dataKeys = useMemo(() => {
|
| 207 |
+
const first = chartData[0];
|
| 208 |
+
if (!first) return [];
|
| 209 |
+
return Object.keys(first).filter((k) => k !== "timestamp");
|
| 210 |
}, [chartData]);
|
| 211 |
|
| 212 |
+
// visibleKeys IS user-facing state (column toggles). Reset it whenever
|
| 213 |
+
// the underlying schema changes — keying off the joined dataKeys string
|
| 214 |
+
// catches both episode navigations and combine/split toggles.
|
| 215 |
+
const dataKeysSig = dataKeys.join("|");
|
| 216 |
+
const [visibleKeys, setVisibleKeys] = useState<string[]>(dataKeys);
|
| 217 |
+
const lastSigRef = useRef(dataKeysSig);
|
| 218 |
+
if (lastSigRef.current !== dataKeysSig) {
|
| 219 |
+
lastSigRef.current = dataKeysSig;
|
| 220 |
+
// Setting state during render is fine here — React schedules a
|
| 221 |
+
// re-render and discards the in-progress one. This pattern is
|
| 222 |
+
// documented as "Storing information from previous renders".
|
| 223 |
+
setVisibleKeys(dataKeys);
|
| 224 |
+
}
|
| 225 |
+
|
| 226 |
const { groups, singles, groupColorMap } = useMemo(() => {
|
| 227 |
const grouped: Record<string, string[]> = {};
|
| 228 |
const singleList: string[] = [];
|