mishig HF Staff commited on
Commit
d2f8acf
·
verified ·
1 Parent(s): 1a13cb6

Sync from GitHub via hub-sync

Browse files
Files changed (1) hide show
  1. src/components/data-recharts.tsx +30 -13
src/components/data-recharts.tsx CHANGED
@@ -1,6 +1,12 @@
1
  "use client";
2
 
3
- import React, { useCallback, useEffect, useMemo, useState } from "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
- useEffect(() => {
202
- if (!chartData || chartData.length === 0) return;
203
- // Get all keys except timestamp from the first row
204
- const keys = Object.keys(chartData[0]).filter((k) => k !== "timestamp");
205
- setDataKeys(keys);
206
- setVisibleKeys(keys);
 
 
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[] = [];