@@ -5,6 +5,7 @@ import { type ActionFunctionArgs, type LoaderFunctionArgs } from "@remix-run/ser
55import type { TaskRunStatus } from "@trigger.dev/database" ;
66import type { PanelHandle } from "@window-splitter/react" ;
77import { Fragment , Suspense , useCallback , useEffect , useMemo , useRef , useState } from "react" ;
8+ import { ClientOnly } from "remix-utils/client-only" ;
89import { Bar , BarChart , ReferenceLine , Tooltip , type TooltipProps , YAxis } from "recharts" ;
910import { TypedAwait , typeddefer , useTypedLoaderData } from "remix-typedjson" ;
1011import { BeakerIcon } from "~/assets/icons/BeakerIcon" ;
@@ -443,27 +444,37 @@ function TaskRow({
443444 < TaskFileName fileName = { item . filePath } variant = "extra-extra-small" />
444445 </ TableCell >
445446 < TableCell to = { rowPath } >
446- < Suspense fallback = { < Spinner color = "blue" className = "size-3" /> } >
447- < TypedAwait resolve = { runningStates } errorElement = { < FailedToLoadStats /> } >
448- { ( data ) => < RunningCell state = { data [ item . slug ] } /> }
449- </ TypedAwait >
450- </ Suspense >
447+ { /* Render the deferred stats client-side. A streamed Suspense boundary still pending at
448+ hydration otherwise bails to client rendering and throws React #421. */ }
449+ < ClientOnly fallback = { < Spinner color = "blue" className = "size-3" /> } >
450+ { ( ) => (
451+ < Suspense fallback = { < Spinner color = "blue" className = "size-3" /> } >
452+ < TypedAwait resolve = { runningStates } errorElement = { < FailedToLoadStats /> } >
453+ { ( data ) => < RunningCell state = { data [ item . slug ] } /> }
454+ </ TypedAwait >
455+ </ Suspense >
456+ ) }
457+ </ ClientOnly >
451458 </ TableCell >
452459 < TableCell to = { rowPath } actionClassName = "py-1.5" >
453460 < div style = { { width : ACTIVITY_CELL_WIDTH , height : ACTIVITY_CHART_HEIGHT } } >
454461 < div hidden = { isPanelAnimating } >
455- < Suspense fallback = { < TaskActivityBlankState /> } >
456- < TypedAwait resolve = { hourlyActivity } errorElement = { < FailedToLoadStats /> } >
457- { ( data ) => {
458- const taskData = data [ item . slug ] ;
459- return taskData && taskData . length > 0 ? (
460- < TaskActivityGraph activity = { taskData } />
461- ) : (
462- < TaskActivityBlankState />
463- ) ;
464- } }
465- </ TypedAwait >
466- </ Suspense >
462+ < ClientOnly fallback = { < TaskActivityBlankState /> } >
463+ { ( ) => (
464+ < Suspense fallback = { < TaskActivityBlankState /> } >
465+ < TypedAwait resolve = { hourlyActivity } errorElement = { < FailedToLoadStats /> } >
466+ { ( data ) => {
467+ const taskData = data [ item . slug ] ;
468+ return taskData && taskData . length > 0 ? (
469+ < TaskActivityGraph activity = { taskData } />
470+ ) : (
471+ < TaskActivityBlankState />
472+ ) ;
473+ } }
474+ </ TypedAwait >
475+ </ Suspense >
476+ ) }
477+ </ ClientOnly >
467478 </ div >
468479 </ div >
469480 </ TableCell >
0 commit comments