最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - I had an issue today with window.addEventListener and React Native - Stack Overflow

programmeradmin4浏览0评论

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
Add a ment  | 

1 Answer 1

Reset to default 4

The 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.

发布评论

评论列表(0)

  1. 暂无评论