1- import { useEffect , useRef , useState , useCallback , useMemo } from 'react'
1+ import { useEffect , useState , useCallback , useMemo } from 'react'
22import { Bar , BarChart , CartesianGrid , XAxis , YAxis , TooltipProps } from 'recharts'
33import { DateRange } from 'react-day-picker'
44import { Card , CardContent , CardDescription , CardHeader , CardTitle } from '@/components/ui/card'
@@ -107,15 +107,12 @@ function CustomBarTooltip({ active, payload, period }: TooltipProps<number, stri
107107}
108108
109109export function CostumeBarChart ( { nodeId } : CostumeBarChartProps ) {
110- const [ chartKey , setChartKey ] = useState ( 0 )
111110 const [ selectedAdmin , setSelectedAdmin ] = useState < string > ( 'all' )
112111 const [ selectedTime , setSelectedTime ] = useState < TrafficShortcutKey > ( '1w' )
113112 const [ showCustomRange , setShowCustomRange ] = useState ( false )
114113 const [ customRange , setCustomRange ] = useState < DateRange | undefined > ( undefined )
115114 const [ windowWidth , setWindowWidth ] = useState < number > ( ( ) => ( typeof window !== 'undefined' ? window . innerWidth : 1024 ) )
116115
117- const chartContainerRef = useRef < HTMLDivElement > ( null )
118-
119116 const { t, i18n } = useTranslation ( )
120117 const dir = useDirDetection ( )
121118 const shouldUseNodeUsage = selectedAdmin === 'all'
@@ -221,94 +218,18 @@ export function CostumeBarChart({ nodeId }: CostumeBarChartProps) {
221218 return getXAxisIntervalForShortcut ( selectedTime , chartData . length , { minuteForOneHour : true } )
222219 } , [ showCustomRange , customRange , activePeriod , chartData . length , selectedTime , windowWidth ] )
223220
224- const refreshChartInstant = useCallback ( ( ) => {
225- if ( chartData . length > 0 ) {
226- setChartKey ( previous => previous + 1 )
227- }
228- } , [ chartData . length ] )
229-
230- const lastRerenderTime = useRef < number > ( 0 )
231- const rerenderTimeout = useRef < NodeJS . Timeout > ( )
232-
233- const refreshChartThrottled = useCallback ( ( ) => {
234- const now = Date . now ( )
235-
236- if ( now - lastRerenderTime . current < 100 ) {
237- if ( rerenderTimeout . current ) {
238- clearTimeout ( rerenderTimeout . current )
239- }
240- rerenderTimeout . current = setTimeout ( ( ) => {
241- refreshChartThrottled ( )
242- } , 100 )
243- return
244- }
245-
246- if ( chartData . length > 0 ) {
247- lastRerenderTime . current = now
248- setChartKey ( previous => previous + 1 )
249- }
250- } , [ chartData . length ] )
251-
252221 useEffect ( ( ) => {
253- let resizeTimeout : NodeJS . Timeout
254-
255222 const handleResize = ( ) => {
256223 setWindowWidth ( window . innerWidth )
257- clearTimeout ( resizeTimeout )
258- resizeTimeout = setTimeout ( ( ) => {
259- refreshChartThrottled ( )
260- } , 150 )
261224 }
262225
226+ handleResize ( )
263227 window . addEventListener ( 'resize' , handleResize )
264228
265- const resizeObserver = new ResizeObserver ( entries => {
266- for ( const entry of entries ) {
267- if ( entry . target === chartContainerRef . current ) {
268- const { width, height } = entry . contentRect
269- if ( width > 0 && height > 0 ) {
270- handleResize ( )
271- }
272- }
273- }
274- } )
275-
276- if ( chartContainerRef . current ) {
277- resizeObserver . observe ( chartContainerRef . current )
278- }
279-
280- const mutationObserver = new MutationObserver ( mutations => {
281- const hasSidebarChange = mutations . some ( mutation => mutation . type === 'attributes' && ( mutation . attributeName === 'class' || mutation . attributeName === 'data-state' ) )
282- if ( hasSidebarChange ) {
283- refreshChartInstant ( )
284- }
285- } )
286-
287- mutationObserver . observe ( document . body , {
288- attributes : true ,
289- attributeFilter : [ 'class' , 'data-sidebar-state' , 'data-state' ] ,
290- childList : false ,
291- subtree : false ,
292- } )
293-
294- const sidebar = document . querySelector ( '[data-sidebar]' ) || document . querySelector ( 'aside' )
295- if ( sidebar ) {
296- mutationObserver . observe ( sidebar , {
297- attributes : true ,
298- attributeFilter : [ 'class' , 'data-state' ] ,
299- } )
300- }
301-
302229 return ( ) => {
303- clearTimeout ( resizeTimeout )
304- if ( rerenderTimeout . current ) {
305- clearTimeout ( rerenderTimeout . current )
306- }
307230 window . removeEventListener ( 'resize' , handleResize )
308- resizeObserver . disconnect ( )
309- mutationObserver . disconnect ( )
310231 }
311- } , [ refreshChartThrottled , refreshChartInstant ] )
232+ } , [ ] )
312233
313234 const handleTimeSelect = useCallback ( ( value : string ) => {
314235 setSelectedTime ( value as TrafficShortcutKey )
@@ -364,7 +285,7 @@ export function CostumeBarChart({ nodeId }: CostumeBarChartProps) {
364285 </ span >
365286 </ div >
366287 </ CardHeader >
367- < CardContent ref = { chartContainerRef } dir = { dir } className = "px-4 pt-4 sm:px-6 sm:pt-8" >
288+ < CardContent dir = { dir } className = "px-4 pt-4 sm:px-6 sm:pt-8" >
368289 { isLoading ? (
369290 < div className = "flex max-h-[300px] min-h-[150px] w-full items-center justify-center sm:max-h-[400px] sm:min-h-[200px]" >
370291 < Skeleton className = "h-[250px] w-full sm:h-[300px]" />
@@ -374,7 +295,6 @@ export function CostumeBarChart({ nodeId }: CostumeBarChartProps) {
374295 ) : (
375296 < div className = "mx-auto w-full max-w-7xl" >
376297 < ChartContainer
377- key = { chartKey }
378298 dir = "ltr"
379299 config = { chartConfig }
380300 className = "max-h-[300px] min-h-[150px] w-full overflow-x-auto sm:max-h-[400px] sm:min-h-[200px]"
0 commit comments