From 31066d4ebe2097c18f79bf8cba1222c07e9e9881 Mon Sep 17 00:00:00 2001
From: Ali Idrizi <20397725+ali-idrizi@users.noreply.github.com>
Date: Fri, 3 Oct 2025 20:21:19 +0200
Subject: [PATCH 1/3] fix(useViewportSize): update size after hydration
---
.../@react-aria/utils/src/useViewportSize.ts | 1 +
.../utils/test/useViewportSize.ssr.test.tsx | 19 ++++++++++++++++++-
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/packages/@react-aria/utils/src/useViewportSize.ts b/packages/@react-aria/utils/src/useViewportSize.ts
index 30fc9d26385..e40af6efd51 100644
--- a/packages/@react-aria/utils/src/useViewportSize.ts
+++ b/packages/@react-aria/utils/src/useViewportSize.ts
@@ -68,6 +68,7 @@ export function useViewportSize(): ViewportSize {
window.addEventListener('blur', onBlur, true);
+ onResize();
if (!visualViewport) {
window.addEventListener('resize', onResize);
} else {
diff --git a/packages/@react-aria/utils/test/useViewportSize.ssr.test.tsx b/packages/@react-aria/utils/test/useViewportSize.ssr.test.tsx
index a5dcf31ae6c..37b20864174 100644
--- a/packages/@react-aria/utils/test/useViewportSize.ssr.test.tsx
+++ b/packages/@react-aria/utils/test/useViewportSize.ssr.test.tsx
@@ -10,7 +10,7 @@
* governing permissions and limitations under the License.
*/
-import {testSSR} from '@react-spectrum/test-utils-internal';
+import {testSSR, screen} from '@react-spectrum/test-utils-internal';
describe('useViewportSize SSR', () => {
it('should render without errors', async () => {
@@ -25,4 +25,21 @@ describe('useViewportSize SSR', () => {
`);
});
+
+ it('should update dimensions after hydration', async () => {
+ await testSSR(__filename, `
+ import {useViewportSize} from '../src';
+
+ function Viewport() {
+ let size = useViewportSize();
+ return
{size.width}x{size.height}
;
+ }
+
+
+ `, () => {
+ expect(screen.getByTestId('viewport')).toHaveTextContent('0x0');
+ });
+
+ expect(screen.getByTestId('viewport')).not.toHaveTextContent('0x0');
+ });
});
From 24d1eb41485c74b7318dbd06a66a7e5110479637 Mon Sep 17 00:00:00 2001
From: Ali Idrizi <20397725+ali-idrizi@users.noreply.github.com>
Date: Fri, 3 Oct 2025 20:44:33 +0200
Subject: [PATCH 2/3] fix import order
---
packages/@react-aria/utils/test/useViewportSize.ssr.test.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/@react-aria/utils/test/useViewportSize.ssr.test.tsx b/packages/@react-aria/utils/test/useViewportSize.ssr.test.tsx
index 37b20864174..e14deb7b3bc 100644
--- a/packages/@react-aria/utils/test/useViewportSize.ssr.test.tsx
+++ b/packages/@react-aria/utils/test/useViewportSize.ssr.test.tsx
@@ -10,7 +10,7 @@
* governing permissions and limitations under the License.
*/
-import {testSSR, screen} from '@react-spectrum/test-utils-internal';
+import {screen, testSSR} from '@react-spectrum/test-utils-internal';
describe('useViewportSize SSR', () => {
it('should render without errors', async () => {
From c49afc2ac9fe0fffca5d409c99ff6c4fc94d5ab6 Mon Sep 17 00:00:00 2001
From: Ali Idrizi <20397725+ali-idrizi@users.noreply.github.com>
Date: Sat, 4 Oct 2025 11:57:47 +0200
Subject: [PATCH 3/3] fix(useViewportSize): update size within the useEffect
unconditionally
---
.../@react-aria/utils/src/useViewportSize.ts | 28 +++++++++----------
1 file changed, 13 insertions(+), 15 deletions(-)
diff --git a/packages/@react-aria/utils/src/useViewportSize.ts b/packages/@react-aria/utils/src/useViewportSize.ts
index e40af6efd51..ed6f6f765e5 100644
--- a/packages/@react-aria/utils/src/useViewportSize.ts
+++ b/packages/@react-aria/utils/src/useViewportSize.ts
@@ -26,6 +26,15 @@ export function useViewportSize(): ViewportSize {
let [size, setSize] = useState(() => isSSR ? {width: 0, height: 0} : getViewportSize());
useEffect(() => {
+ let updateSize = (newSize: ViewportSize) => {
+ setSize(size => {
+ if (newSize.width === size.width && newSize.height === size.height) {
+ return size;
+ }
+ return newSize;
+ });
+ };
+
// Use visualViewport api to track available height even on iOS virtual keyboard opening
let onResize = () => {
// Ignore updates when zoomed.
@@ -33,13 +42,7 @@ export function useViewportSize(): ViewportSize {
return;
}
- setSize(size => {
- let newSize = getViewportSize();
- if (newSize.width === size.width && newSize.height === size.height) {
- return size;
- }
- return newSize;
- });
+ updateSize(getViewportSize());
};
// When closing the keyboard, iOS does not fire the visual viewport resize event until the animation is complete.
@@ -54,21 +57,16 @@ export function useViewportSize(): ViewportSize {
// Wait one frame to see if a new element gets focused.
frame = requestAnimationFrame(() => {
if (!document.activeElement || !willOpenKeyboard(document.activeElement)) {
- setSize(size => {
- let newSize = {width: window.innerWidth, height: window.innerHeight};
- if (newSize.width === size.width && newSize.height === size.height) {
- return size;
- }
- return newSize;
- });
+ updateSize({width: window.innerWidth, height: window.innerHeight});
}
});
}
};
+ updateSize(getViewportSize());
+
window.addEventListener('blur', onBlur, true);
- onResize();
if (!visualViewport) {
window.addEventListener('resize', onResize);
} else {