I was trying to implement dynamic re-rendering of my react application using this function I found here:
function useWindowSize() {
const [size, setSize] = useState([0, 0]);
useLayoutEffect(
() => {
function updateSize() {
setSize([window.innerWidth, window.innerHeight]);
}
window.addEventListener("resize", updateSize);
updateSize();
return () => window.removeEventListener("resize", updateSize);
},[]);
return size;
}
function ShowWindowDimensions(props) {
const [width, height] = useWindowSize();
return (
<span>
Window size: {width} x {height}
</span>
);
}
Link to my app:
I was able to get everything working perfectly when displaying my app in the browser on my desktop. I'm using expo to run the app. The problem came when I tried to run the app on my android phone. I was getting an error at launch.
COMPONENT EXCEPTION: window.addEventListener is not a function
I was able to get it working with a solution I found here:
That solution says that the event listener for window doesn't exist in react native, so we have to mock it. I don't understand what that means. I still don't know why the solution I found worked. I would like to understand. Can someone enlighten me?
I was trying to implement dynamic re-rendering of my react application using this function I found here: https://stackoverflow./a/19014495/7838374
function useWindowSize() {
const [size, setSize] = useState([0, 0]);
useLayoutEffect(
() => {
function updateSize() {
setSize([window.innerWidth, window.innerHeight]);
}
window.addEventListener("resize", updateSize);
updateSize();
return () => window.removeEventListener("resize", updateSize);
},[]);
return size;
}
function ShowWindowDimensions(props) {
const [width, height] = useWindowSize();
return (
<span>
Window size: {width} x {height}
</span>
);
}
Link to my app: https://github./Intetra/aubreyw
I was able to get everything working perfectly when displaying my app in the browser on my desktop. I'm using expo to run the app. The problem came when I tried to run the app on my android phone. I was getting an error at launch.
COMPONENT EXCEPTION: window.addEventListener is not a function
I was able to get it working with a solution I found here: https://stackoverflow./a/61470685/7838374
That solution says that the event listener for window doesn't exist in react native, so we have to mock it. I don't understand what that means. I still don't know why the solution I found worked. I would like to understand. Can someone enlighten me?
Share Improve this question asked Feb 10, 2021 at 21:17 Aubrey WiedemanAubrey Wiedeman 451 gold badge1 silver badge7 bronze badges 1- You want to import Dimensions from react-native and use Dimensions.addEventListener to do it. But then you also need to debounce the thing. It gets kinda plicated, but you can google it. Debounce means you wait a bit after you resize the window before calculating the resizing otherwise it'll try to resize 60+ times a seconds which kills performance – wongx Commented Dec 4, 2021 at 2:43
1 Answer
Reset to default 4The browser environment is different than the React Native environment in some ways, despite the fact that both use Javascript. This means that while the language is the same, some of the underlying features may be different, meaning they could behave differently, or exist in one place and not the other.
window.addEventListener
is an example of something that we can expect to exist in the browser world, but is not implemented in React Native. This gets slightly more plicated, of course, by Expo, which allows running React Native code on the web by shimming certain features, trying to bridge some of the difference between the two worlds.
Because of the dynamic nature of Javascript, even though window.addEventListener isn't provided by React Native on iOS/Android, we can just add it to our environment by defining it ourselves. That's what the solution you found (window.addEventListener = x => x
) does -- it just adds a function that doesn't actually do anything (it takes x
as a parameter and returns x
as a result). This is sometimes referred to as a mock -- you'll often see this in the testing world.
On React Native on the device, in my testing, your solution wouldn't produce an error, but it also wouldn't actually give you the dimensions. Luckily, you can use Dimensions
to get the screen size, which Expo also exposes in the web version. So, this will looks to return the correct size on both the native app and the Expo web version:
function useWindowSize() {
const [size, setSize] = React.useState([0, 0]);
React.useLayoutEffect(
() => {
console.log("Layout effect")
function updateSize() {
setSize([Dimensions.get('window').width, Dimensions.get('window').height])
}
window.addEventListener("resize", updateSize);
updateSize();
return () => window.removeEventListener("resize", updateSize);
},[]);
return size;
}
Note, you should do some testing to see what happens when rotating, resizing, etc -- I only made sure the basic functionality works.
Here's a snack with the code in context: https://snack.expo.io/Mofut1jHa
Also note that window.removeEventListener
has to be mocked as well, which you can see in the Snack.