Skip to content

Commit 808343c

Browse files
fix(useViewportSize): update size after hydration (adobe#8966)
* fix(useViewportSize): update size after hydration * fix import order * fix(useViewportSize): update size within the useEffect unconditionally --------- Co-authored-by: Robert Snow <rsnow@adobe.com>
1 parent 855cc71 commit 808343c

2 files changed

Lines changed: 31 additions & 15 deletions

File tree

packages/@react-aria/utils/src/useViewportSize.ts

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,23 @@ export function useViewportSize(): ViewportSize {
2626
let [size, setSize] = useState(() => isSSR ? {width: 0, height: 0} : getViewportSize());
2727

2828
useEffect(() => {
29+
let updateSize = (newSize: ViewportSize) => {
30+
setSize(size => {
31+
if (newSize.width === size.width && newSize.height === size.height) {
32+
return size;
33+
}
34+
return newSize;
35+
});
36+
};
37+
2938
// Use visualViewport api to track available height even on iOS virtual keyboard opening
3039
let onResize = () => {
3140
// Ignore updates when zoomed.
3241
if (visualViewport && visualViewport.scale > 1) {
3342
return;
3443
}
3544

36-
setSize(size => {
37-
let newSize = getViewportSize();
38-
if (newSize.width === size.width && newSize.height === size.height) {
39-
return size;
40-
}
41-
return newSize;
42-
});
45+
updateSize(getViewportSize());
4346
};
4447

4548
// When closing the keyboard, iOS does not fire the visual viewport resize event until the animation is complete.
@@ -54,18 +57,14 @@ export function useViewportSize(): ViewportSize {
5457
// Wait one frame to see if a new element gets focused.
5558
frame = requestAnimationFrame(() => {
5659
if (!document.activeElement || !willOpenKeyboard(document.activeElement)) {
57-
setSize(size => {
58-
let newSize = {width: window.innerWidth, height: window.innerHeight};
59-
if (newSize.width === size.width && newSize.height === size.height) {
60-
return size;
61-
}
62-
return newSize;
63-
});
60+
updateSize({width: window.innerWidth, height: window.innerHeight});
6461
}
6562
});
6663
}
6764
};
6865

66+
updateSize(getViewportSize());
67+
6968
window.addEventListener('blur', onBlur, true);
7069

7170
if (!visualViewport) {

packages/@react-aria/utils/test/useViewportSize.ssr.test.tsx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
* governing permissions and limitations under the License.
1111
*/
1212

13-
import {testSSR} from '@react-spectrum/test-utils-internal';
13+
import {screen, testSSR} from '@react-spectrum/test-utils-internal';
1414

1515
describe('useViewportSize SSR', () => {
1616
it('should render without errors', async () => {
@@ -25,4 +25,21 @@ describe('useViewportSize SSR', () => {
2525
<Viewport />
2626
`);
2727
});
28+
29+
it('should update dimensions after hydration', async () => {
30+
await testSSR(__filename, `
31+
import {useViewportSize} from '../src';
32+
33+
function Viewport() {
34+
let size = useViewportSize();
35+
return <div data-testid="viewport">{size.width}x{size.height}</div>;
36+
}
37+
38+
<Viewport />
39+
`, () => {
40+
expect(screen.getByTestId('viewport')).toHaveTextContent('0x0');
41+
});
42+
43+
expect(screen.getByTestId('viewport')).not.toHaveTextContent('0x0');
44+
});
2845
});

0 commit comments

Comments
 (0)