From 09dbf72b629bed74c0e45a1849290c644d48f344 Mon Sep 17 00:00:00 2001 From: louzhedong Date: Sun, 7 Jun 2026 22:05:25 +0800 Subject: [PATCH] feat: prefer screen.orientation change events --- src/useOrientation.ts | 15 +++++++++++++-- tests/useOrientation.test.ts | 28 ++++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/useOrientation.ts b/src/useOrientation.ts index b5365af90f..a34c0ed221 100644 --- a/src/useOrientation.ts +++ b/src/useOrientation.ts @@ -16,6 +16,9 @@ const useOrientation = (initialState: OrientationState = defaultState) => { useEffect(() => { const screen = window.screen; + const orientation = screen.orientation as + | (ScreenOrientation & EventTarget) + | undefined; let mounted = true; const onChange = () => { @@ -36,12 +39,20 @@ const useOrientation = (initialState: OrientationState = defaultState) => { } }; - on(window, 'orientationchange', onChange); + if (orientation?.addEventListener) { + on(orientation, 'change', onChange); + } else { + on(window, 'orientationchange', onChange); + } onChange(); return () => { mounted = false; - off(window, 'orientationchange', onChange); + if (orientation?.removeEventListener) { + off(orientation, 'change', onChange); + } else { + off(window, 'orientationchange', onChange); + } }; }, []); diff --git a/tests/useOrientation.test.ts b/tests/useOrientation.test.ts index df45546263..68761800dd 100644 --- a/tests/useOrientation.test.ts +++ b/tests/useOrientation.test.ts @@ -13,10 +13,10 @@ describe('useOrientation', () => { }); beforeEach(() => { - (window.screen.orientation as object) = { + (window.screen.orientation as unknown) = Object.assign(new EventTarget(), { type: 'landscape-primary', angle: 0, - }; + }); (window.orientation as number) = 0; }); @@ -32,10 +32,16 @@ describe('useOrientation', () => { return renderHook(() => useOrientation(...args)); } - function triggerOrientation(type: string, angle: number) { + function triggerScreenOrientation(type: string, angle: number) { (window.screen.orientation.type as string) = type; (window.screen.orientation.angle as number) = angle; + (window.screen.orientation as EventTarget).dispatchEvent(new Event('change')); + } + + function triggerWindowOrientation(angle: number) { + (window.orientation as number) = angle; + window.dispatchEvent(new Event('orientationchange')); } @@ -55,10 +61,24 @@ describe('useOrientation', () => { }); it('should re-render after orientation change on closest RAF', () => { + (window.screen.orientation as unknown) = undefined; + + const hook = getHook(); + + act(() => { + triggerWindowOrientation(180); + requestAnimationFrame.step(); + }); + + expect(hook.result.current.type).toBe(''); + expect(hook.result.current.angle).toBe(180); + }); + + it('should re-render after screen.orientation change', () => { const hook = getHook(); act(() => { - triggerOrientation('portrait-secondary', 180); + triggerScreenOrientation('portrait-secondary', 180); requestAnimationFrame.step(); });