Last active
April 9, 2025 19:48
-
-
Save petrbela/d859308b22a09b4233fd72e26f2f9725 to your computer and use it in GitHub Desktop.
useWindowDimensions fix for https://github.com/facebook/react-native/issues/29290
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// used for Expo Go | |
import { | |
Orientation, | |
addOrientationChangeListener, | |
getOrientationAsync, | |
removeOrientationChangeListener, | |
} from 'expo-screen-orientation' | |
import { useEffect, useState } from 'react' | |
import { Dimensions } from 'react-native' | |
/** | |
* Return actual window dimensions even when orientation changes. | |
* | |
* @see https://github.com/facebook/react-native/issues/29290 | |
* @returns window dimensions | |
*/ | |
export function useDimensions() { | |
const [dimensions, setDimensions] = useState(Dimensions.get('window')) | |
useEffect(() => { | |
getOrientationAsync().then((orientation) => { | |
setDimensions(fixDimensions(orientation)) | |
}) | |
const listener = addOrientationChangeListener(({ orientationInfo }) => { | |
setDimensions(fixDimensions(orientationInfo.orientation)) | |
}) | |
return () => { | |
removeOrientationChangeListener(listener) | |
} | |
}, []) | |
return dimensions | |
} | |
function fixDimensions(orientation: Orientation) { | |
const window = Dimensions.get('window') | |
if ( | |
(orientation === Orientation.LANDSCAPE_LEFT || | |
orientation === Orientation.LANDSCAPE_RIGHT) && | |
window.width < window.height | |
) { | |
return { ...window, width: window.height, height: window.width } | |
} else if ( | |
(orientation === Orientation.PORTRAIT_UP || | |
orientation === Orientation.PORTRAIT_DOWN) && | |
window.width > window.height | |
) { | |
return { ...window, width: window.height, height: window.width } | |
} | |
return window | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// used for native build | |
import { useEffect, useState } from 'react' | |
import { Dimensions, useWindowDimensions } from 'react-native' | |
import { | |
orientation as Orientation, | |
addOrientationListener, | |
getOrientation, | |
removeOrientationListener, | |
} from 'react-native-orientation' | |
/** | |
* Return actual window dimensions even when orientation changes. | |
* | |
* @see https://github.com/facebook/react-native/issues/29290 | |
* @returns window dimensions | |
*/ | |
export function useDimensions() { | |
const windowDimensions = useWindowDimensions() | |
const [dimensions, setDimensions] = useState(windowDimensions) | |
function updateDimensions() { | |
getOrientation((err, orientation) => { | |
if (err) { | |
console.error(err) | |
} else { | |
setDimensions(fixDimensions(orientation)) | |
} | |
}) | |
} | |
useEffect(() => { | |
// Update dimensions when orientation changes | |
const orientationListener = (orientation: Orientation) => { | |
setDimensions(fixDimensions(orientation)) | |
} | |
addOrientationListener(orientationListener) | |
return () => { | |
removeOrientationListener(orientationListener) | |
} | |
}, []) | |
useEffect(() => { | |
// Update dimensions when window size changes | |
// FIXME: on Mac (Designed for iPad), there's currently no native window size change event in UIKit, so the trigger is delayed until the window is blurred or focused | |
updateDimensions() | |
}, [windowDimensions]) | |
return dimensions | |
} | |
function fixDimensions(orientation: Orientation) { | |
const window = Dimensions.get('window') | |
if (orientation === 'LANDSCAPE' && window.width < window.height) { | |
return { ...window, width: window.height, height: window.width } | |
} else if ( | |
(orientation === 'PORTRAIT' || orientation === 'PORTRAITUPSIDEDOWN') && | |
window.width > window.height | |
) { | |
return { ...window, width: window.height, height: window.width } | |
} | |
return window | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// used for web | |
import { useWindowDimensions } from 'react-native' | |
export const useDimensions = useWindowDimensions |
Hi , did u find any solutions ?
I added an implementation using react-native-orientation that I use for native builds.
Since that native package can't be used when I test in Expo Go, I default to expo implementation by adding config.resolver.sourceExts.unshift('expo.ts', 'expo.tsx')
to my metro.config.js
that's used only by the Expo packager.
hi , for me it works normally in all build.. i use expo 52.. did u try 52?
I use import * as ScreenOrientation from "expo-screen-orientation";
fwiw I've now switched to useSafeAreaFrame
as described facebook/react-native#29290 (comment) which seems to work so far, is supported in Expo (Go) out of the box and looks much cleaner.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Just found out expo-screen-orientation is broken in native builds expo/expo#15009 so a different solution might be needed.