diff --git a/src/app/charts/page.tsx b/src/app/charts/page.tsx index 5ebee69..0babe7d 100644 --- a/src/app/charts/page.tsx +++ b/src/app/charts/page.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useState, useEffect, useMemo } from 'react'; +import { useState, useEffect, useMemo, Profiler } from 'react'; import { Chart as ChartJS, CategoryScale, @@ -65,6 +65,17 @@ ChartJS.register( Legend, ); +export function onRender( + id: string, + phase: 'mount' | 'update' | 'nested-update', + actualDuration: number, + baseDuration: number, + startTime: number, + commitTime: number, +): void { + // console.log(`Profiler [${id}] - ${phase} - ${actualDuration} ms`); +} + export default function Charts() { const [chartData, setChartData] = useState([]); const [monthList, setMonthList] = useState([]); @@ -242,48 +253,52 @@ export default function Charts() { }, }; + console.log('render chart page'); + return ( <> -
- - -
- +
+ - - {!expandedLineSelector && ( -
- {chartData.length > 0 ? ( - - ) : ( -
-

Please select data

-
- )} -
- )} + setDayOfWeek={setDayOfWeek} + >
+ +
+ + + {!expandedLineSelector && ( +
+ {chartData.length > 0 ? ( + + ) : ( +
+

Please select data

+
+ )} +
+ )} +
-
+ ); } diff --git a/src/app/inputComponents/metroLineTableRow.tsx b/src/app/inputComponents/metroLineTableRow.tsx index 5821d52..5d69457 100644 --- a/src/app/inputComponents/metroLineTableRow.tsx +++ b/src/app/inputComponents/metroLineTableRow.tsx @@ -1,7 +1,7 @@ 'use client'; import * as Checkbox from '@radix-ui/react-checkbox'; -import { useState, useEffect } from 'react'; +import { useState, useEffect, useMemo } from 'react'; import { type Line } from '../common/types'; import { getLineColor } from '../common/lines'; import { Metric } from '../charts/page'; @@ -38,7 +38,11 @@ export default function MetroLineTableRow({ }, events: [], - animation: false, + animation: { + onComplete: function () { + setIsMounted(true); + }, + }, spanGaps: true, normalized: true, scales: { @@ -65,35 +69,76 @@ export default function MetroLineTableRow({ }, }; - let chartDataset: ChartData[] = []; + // let chartDataset: ChartData[] = []; + + const chartData: ChartData[] = useMemo( + () => + lineMetrics + ? [ + { + borderColor: getLineColor(Number(line.id)), + data: lineMetrics.map((metric) => ({ + time: metric.year + ' ' + metric.month, + stat: metric[dayOfWeek], + })), + id: Number(line), + }, + ] + : [], + // eslint-disable-next-line react-hooks/exhaustive-deps + [JSON.stringify(lineMetrics)], + ); useEffect(() => { + if (!expanded) { + return; + } + setIsMounted(false); - lineMetrics - ? chartDataset.push({ - borderColor: getLineColor(Number(line.id)), - data: lineMetrics.map((metric) => ({ - time: metric.year + ' ' + metric.month, - stat: metric[dayOfWeek], - })), - id: Number(line), - }) - : ''; + const chartDataset: ChartData[] = lineMetrics + ? [ + { + borderColor: getLineColor(Number(line.id)), + data: lineMetrics.map((metric) => ({ + time: metric.year + ' ' + metric.month, + stat: metric[dayOfWeek], + })), + id: Number(line), + }, + ] + : []; setData(chartDataset); - - setIsMounted(true); // eslint-disable-next-line react-hooks/exhaustive-deps }, [ line, dayOfWeek, // eslint-disable-next-line react-hooks/exhaustive-deps JSON.stringify(lineMetrics), - // eslint-disable-next-line react-hooks/exhaustive-deps - JSON.stringify(chartDataset), ]); + const hashCode = function (s) { + var h = 0, + l = s.length, + i = 0; + if (l > 0) while (i < l) h = ((h << 5) - h + s.charCodeAt(i++)) | 0; + return h; + }; + + if (line.name === 'Line 2') { + console.log('Render Row -----------------------'); + console.log('Render Row - Line ' + line.name); + console.log('Render Row - Metrics Length ' + lineMetrics?.length); + console.log('Render Row - Mounted ' + isMounted); + console.log('Render Row - Expanded ' + expanded); + console.log('Render Row - Line ' + JSON.stringify(line)); + console.log('Render Row - Day of Week ' + dayOfWeek); + console.log( + 'Render Row - Chart Data Hash' + hashCode(JSON.stringify(data)), + ); + } + return ( <> + {/* It seems the rendering takes time. We can't use loading because the data itself is already loaded. + Either make more efficient (ex: don't draw points/lines) or use another chart library. + Possible options include web worker, less data points */} {isMounted ? ( { + console.log('Get sorted lines'); // Get column headers that have a sort direction (ex: asc, desc). const sortableColumnHeaders: ColumnHeaderState[] = columnHeaderStates.filter( @@ -184,77 +185,84 @@ export default function LineSelector({ const subtitleClass = 'text-neutral-400'; + console.log('render line selector'); + return ( /* Styled as flexbox so overflow scroll container stretches full height */ -
-
- - Line Selector - - - -
- - {/* Overflow scroll container */} -
- - {/* Only show table header when line selector is expanded */} - {expanded && ( - - - {columnHeaderStates.map( - (columnHeaderState: ColumnHeaderState, index: number) => { - let classNames: string = subtitleClass; - if (columnHeaderState.sortDirection === 'asc') { - classNames = `${classNames} headerSortUp`; - } else if (columnHeaderState.sortDirection === 'desc') { - classNames = `${classNames} headerSortDown`; - } - - return ( - - ); - }, - )} - - - )} - - - {sortedLines.map((line) => { - const lineMetrics: MetricWrapper = lineMetricDataset[line.id]; - - return ( - - ); - })} - -
- onSortLabelClick(columnHeaderState.key) - } - > - {columnHeaderState.label} -
+ +
+
+ + Line Selector + + + +
+ + {/* Overflow scroll container */} +
+ + {/* Only show table header when line selector is expanded */} + {expanded && ( + + + {columnHeaderStates.map( + (columnHeaderState: ColumnHeaderState, index: number) => { + let classNames: string = subtitleClass; + if (columnHeaderState.sortDirection === 'asc') { + classNames = `${classNames} headerSortUp`; + } else if (columnHeaderState.sortDirection === 'desc') { + classNames = `${classNames} headerSortDown`; + } + + return ( + + ); + }, + )} + + + )} + + + {sortedLines.map((line) => { + const lineMetrics: MetricWrapper = lineMetricDataset[line.id]; + + return ( + + ); + })} + +
+ onSortLabelClick(columnHeaderState.key) + } + > + {columnHeaderState.label} +
+
-
+ ); }