From 8547796180c43d5bf8de37f8c1e14a27490aed75 Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Mon, 23 Mar 2026 22:43:23 +0100 Subject: [PATCH 1/2] fix(AnalyticalTable): prevent empty table body flash on first render Use useLayoutEffect instead of useEffect for the isMounted state in VirtualTableBodyContainer to eliminate a one-frame flash where table headers render without any body rows. --- .../AnalyticalTable/TableBody/VirtualTableBodyContainer.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/main/src/components/AnalyticalTable/TableBody/VirtualTableBodyContainer.tsx b/packages/main/src/components/AnalyticalTable/TableBody/VirtualTableBodyContainer.tsx index 6b94d9928e8..c8a7feb966b 100644 --- a/packages/main/src/components/AnalyticalTable/TableBody/VirtualTableBodyContainer.tsx +++ b/packages/main/src/components/AnalyticalTable/TableBody/VirtualTableBodyContainer.tsx @@ -1,7 +1,7 @@ import { enrichEventWithDetails } from '@ui5/webcomponents-react-base'; import { clsx } from 'clsx'; import type { MutableRefObject } from 'react'; -import { useCallback, useEffect, useRef, useState } from 'react'; +import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react'; import type { AnalyticalTablePropTypes, TableInstance } from '../types/index.js'; interface VirtualTableBodyContainerProps { @@ -46,9 +46,9 @@ export const VirtualTableBodyContainer = (props: VirtualTableBodyContainerProps) } = props; const [isMounted, setIsMounted] = useState(false); - useEffect(() => { + useLayoutEffect(() => { if (parentRef.current) { - // Trigger one-time re-render after first render -> safe to set state here + // Trigger one-time synchronous re-render before paint -> safe to set state here // eslint-disable-next-line react-hooks/set-state-in-effect setIsMounted(true); } From ea6a4195e64de9f5abd6a83c53597d3b370ca223 Mon Sep 17 00:00:00 2001 From: Abdelrahman Khattab Date: Wed, 25 Mar 2026 10:31:03 +0100 Subject: [PATCH 2/2] fix(AnalyticalTable): prevent empty table body flash on first render Use useIsomorphicLayoutEffect instead of useEffect when toggling isMounted in VirtualTableBodyContainer so rows render before the first paint. --- .../TableBody/VirtualTableBodyContainer.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/main/src/components/AnalyticalTable/TableBody/VirtualTableBodyContainer.tsx b/packages/main/src/components/AnalyticalTable/TableBody/VirtualTableBodyContainer.tsx index c8a7feb966b..3eb33f812b5 100644 --- a/packages/main/src/components/AnalyticalTable/TableBody/VirtualTableBodyContainer.tsx +++ b/packages/main/src/components/AnalyticalTable/TableBody/VirtualTableBodyContainer.tsx @@ -1,7 +1,7 @@ -import { enrichEventWithDetails } from '@ui5/webcomponents-react-base'; +import { enrichEventWithDetails, useIsomorphicLayoutEffect } from '@ui5/webcomponents-react-base'; import { clsx } from 'clsx'; import type { MutableRefObject } from 'react'; -import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; import type { AnalyticalTablePropTypes, TableInstance } from '../types/index.js'; interface VirtualTableBodyContainerProps { @@ -46,9 +46,9 @@ export const VirtualTableBodyContainer = (props: VirtualTableBodyContainerProps) } = props; const [isMounted, setIsMounted] = useState(false); - useLayoutEffect(() => { + useIsomorphicLayoutEffect(() => { if (parentRef.current) { - // Trigger one-time synchronous re-render before paint -> safe to set state here + // Run before paint so rows appear with the body container (avoids empty-body flash). // eslint-disable-next-line react-hooks/set-state-in-effect setIsMounted(true); }