我今天有一个问题的窗口.addEventListener和React Native



我试图实现动态重新渲染我的反应应用程序使用这个函数,我发现在这里:https://stackoverflow.com/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>
);
}

链接到我的应用:https://github.com/Intetra/aubreyw

当我在桌面上的浏览器中显示我的应用程序时,我能够让一切工作完美。我正在使用expo来运行这个应用程序。当我试图在我的安卓手机上运行这个应用程序时,问题出现了。启动时出现错误

组件异常:window。addEventListener不是一个函数

我在这里找到了一个解决方案,可以让它工作:https://stackoverflow.com/a/61470685/7838374

那个解决方案说window的事件监听器在react native中不存在,所以我们必须模拟它。我不明白那是什么意思。我仍然不知道为什么我找到的解决方案有效。我想了解。有人能开导我吗?

浏览器环境在某些方面与React Native环境不同,尽管两者都使用Javascript。这意味着,虽然语言是相同的,但一些潜在的特性可能不同,这意味着它们的行为可能不同,或者存在于一个地方而不存在于另一个地方。

window.addEventListener是一个我们期望在浏览器世界中存在的东西的例子,但在React Native中没有实现。当然,Expo允许在web上运行React Native代码,通过屏蔽某些功能,试图弥合两个世界之间的一些差异,这就变得稍微复杂了一些。

因为Javascript的动态特性,即使是窗口。addEventListener不是由iOS/Android上的React Native提供的,我们可以通过自己定义它来将它添加到我们的环境中。这就是您发现的解决方案(window.addEventListener = x => x)所做的-它只是添加了一个实际上不做任何事情的函数(它将x作为参数并返回x作为结果)。这有时被称为模拟——您将经常在测试世界中看到这种情况。

在设备上的React Native上,在我的测试中,你的解决方案不会产生错误,但它也不会给你尺寸。幸运的是,您可以使用Dimensions来获取屏幕尺寸,这也是Expo在web版本中提供的。因此,这将在本地应用程序和Expo web版本上返回正确的大小:


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;
}

注意,你应该做一些测试,看看在旋转、调整大小等情况下会发生什么——我只确保基本功能有效。

这里有一个零食与上下文中的代码:https://snack.expo.io/Mofut1jHa

还请注意,window.removeEventListener也必须被嘲笑,您可以在零食中看到。

最新更新