From 0f692f2c2ba0a1b80a957bddec320417ad3f5ee8 Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Wed, 2 Nov 2022 11:26:24 -0700 Subject: [PATCH] [fix] Dimensions.get() should not call change listeners Fixes a bug introduced by 59af091fdb4dd91118b105596a28c093426978b0 Fix #2394 --- .../Dimensions/__tests__/index-test.js | 9 ++- .../src/exports/Dimensions/index.js | 61 ++++++++++--------- 2 files changed, 38 insertions(+), 32 deletions(-) diff --git a/packages/react-native-web/src/exports/Dimensions/__tests__/index-test.js b/packages/react-native-web/src/exports/Dimensions/__tests__/index-test.js index 3a14073f..6abbf1eb 100644 --- a/packages/react-native-web/src/exports/Dimensions/__tests__/index-test.js +++ b/packages/react-native-web/src/exports/Dimensions/__tests__/index-test.js @@ -9,6 +9,8 @@ import Dimensions from '..'; describe('apis/Dimensions', () => { test('get', () => { + const handler = jest.fn(); + Dimensions.addEventListener('change', handler); expect(Dimensions.get('screen')).toMatchInlineSnapshot(` { "fontScale": 1, @@ -25,6 +27,7 @@ describe('apis/Dimensions', () => { "width": 1024, } `); + expect(handler).toHaveBeenCalledTimes(0); }); test('set', () => { @@ -34,21 +37,21 @@ describe('apis/Dimensions', () => { test('addEventListener', () => { const handler = jest.fn(); const subscription = Dimensions.addEventListener('change', handler); - Dimensions._update(); + window.dispatchEvent(new Event('resize')); expect(handler).toHaveBeenCalledTimes(1); expect(handler).toHaveBeenLastCalledWith({ window: Dimensions.get('window'), screen: Dimensions.get('screen') }); subscription.remove(); - Dimensions._update(); + window.dispatchEvent(new Event('resize')); expect(handler).toHaveBeenCalledTimes(1); }); test('removeEventListener', () => { const handler = jest.fn(); Dimensions.removeEventListener('change', handler); - Dimensions._update(); + window.dispatchEvent(new Event('resize')); expect(handler).toHaveBeenCalledTimes(0); }); }); diff --git a/packages/react-native-web/src/exports/Dimensions/index.js b/packages/react-native-web/src/exports/Dimensions/index.js index aa02a273..78d0e2e0 100644 --- a/packages/react-native-web/src/exports/Dimensions/index.js +++ b/packages/react-native-web/src/exports/Dimensions/index.js @@ -46,11 +46,41 @@ const listeners = {}; let shouldInit = canUseDOM; +function update() { + if (!canUseDOM) { + return; + } + + const win = window; + const docEl = win.document.documentElement; + + dimensions.window = { + fontScale: 1, + height: docEl.clientHeight, + scale: win.devicePixelRatio || 1, + width: docEl.clientWidth + }; + + dimensions.screen = { + fontScale: 1, + height: win.screen.height, + scale: win.devicePixelRatio || 1, + width: win.screen.width + }; +} + +function handleResize() { + update(); + if (Array.isArray(listeners['change'])) { + listeners['change'].forEach((handler) => handler(dimensions)); + } +} + export default class Dimensions { static get(dimension: DimensionKey): DisplayMetrics { if (shouldInit) { shouldInit = false; - Dimensions._update(); + update(); } invariant(dimensions[dimension], `No dimension set for key ${dimension}`); return dimensions[dimension]; @@ -71,33 +101,6 @@ export default class Dimensions { } } - static _update() { - if (!canUseDOM) { - return; - } - - const win = window; - const docEl = win.document.documentElement; - - dimensions.window = { - fontScale: 1, - height: docEl.clientHeight, - scale: win.devicePixelRatio || 1, - width: docEl.clientWidth - }; - - dimensions.screen = { - fontScale: 1, - height: win.screen.height, - scale: win.devicePixelRatio || 1, - width: win.screen.width - }; - - if (Array.isArray(listeners['change'])) { - listeners['change'].forEach((handler) => handler(dimensions)); - } - } - static addEventListener( type: DimensionEventListenerType, handler: (DimensionsValue) => void @@ -125,5 +128,5 @@ export default class Dimensions { } if (canUseDOM) { - window.addEventListener('resize', Dimensions._update, false); + window.addEventListener('resize', handleResize, false); }