@@ -25,7 +25,7 @@ import timezone from 'dayjs/plugin/timezone';
2525import utc from 'dayjs/plugin/utc' ;
2626import { useAtom } from 'jotai' ;
2727import { useRouter } from 'next/navigation' ;
28- import { useCallback , useEffect , useState } from 'react' ;
28+ import { useCallback , useMemo , useRef , useState } from 'react' ;
2929import { useBillingData } from '@/app/(main)/billing/data/billing-data' ;
3030import { DataTable } from '@/components/analytics/data-table' ;
3131import { StatCard } from '@/components/analytics/stat-card' ;
@@ -100,19 +100,29 @@ const QUERY_CONFIG = {
100100
101101function LiveUserIndicator ( { websiteId } : { websiteId : string } ) {
102102 const { activeUsers : count } = useRealTimeStats ( websiteId ) ;
103- const [ prevCount , setPrevCount ] = useState ( count ) ;
103+ const prevCountRef = useRef ( count ) ;
104+ const timeoutRef = useRef < NodeJS . Timeout | null > ( null ) ;
104105 const [ change , setChange ] = useState < 'up' | 'down' | null > ( null ) ;
105106
106- useEffect ( ( ) => {
107+ useMemo ( ( ) => {
108+ const prevCount = prevCountRef . current ;
109+
110+ if ( timeoutRef . current ) {
111+ clearTimeout ( timeoutRef . current ) ;
112+ }
113+
107114 if ( count > prevCount ) {
108115 setChange ( 'up' ) ;
116+ timeoutRef . current = setTimeout ( ( ) => setChange ( null ) , 1000 ) ;
109117 } else if ( count < prevCount ) {
110118 setChange ( 'down' ) ;
119+ timeoutRef . current = setTimeout ( ( ) => setChange ( null ) , 1000 ) ;
111120 }
112- const timer = setTimeout ( ( ) => setChange ( null ) , 1000 ) ;
113- setPrevCount ( count ) ;
114- return ( ) => clearTimeout ( timer ) ;
115- } , [ count , prevCount ] ) ;
121+
122+ prevCountRef . current = count ;
123+
124+ return null ;
125+ } , [ count ] ) ;
116126
117127 const getChangeColor = ( ) => {
118128 if ( change === 'up' ) {
@@ -365,28 +375,20 @@ export function WebsiteOverviewTab({
365375 avg_session_duration : visibleMetrics . avg_session_duration ,
366376 } ;
367377
368- useEffect ( ( ) => {
369- let isMounted = true ;
370-
378+ useMemo ( ( ) => {
371379 if ( isRefreshing ) {
372380 const doRefresh = async ( ) => {
373381 try {
374382 await refetchBatch ( ) ;
375- } catch ( error ) {
376- console . error ( 'Failed to refresh data:' , error ) ;
383+ } catch ( refreshError ) {
384+ console . error ( 'Failed to refresh data:' , refreshError ) ;
377385 } finally {
378- if ( isMounted ) {
379- setIsRefreshing ( false ) ;
380- }
386+ setIsRefreshing ( false ) ;
381387 }
382388 } ;
383-
384389 doRefresh ( ) ;
385390 }
386-
387- return ( ) => {
388- isMounted = false ;
389- } ;
391+ return null ;
390392 } , [ isRefreshing , refetchBatch , setIsRefreshing ] ) ;
391393
392394 const isLoading = loading . summary || isRefreshing ;
0 commit comments