javascript - RangeError:本机反应超出了最大调用堆栈大小与expo
问题描述
我正在尝试使用 expo 创建一个 youtube 类型的视频播放器应用程序(仅用于学习目的)并做出原生反应。但是我有一个非常奇怪的问题,每次我保存文件并开始热重载时都会抛出类似的错误
RangeError: Maximum call stack size exceeded
我已经看过这个,发现这个错误是由于递归而发生的。但我在我的代码中找不到任何递归。
但更奇怪的是,第一次应用程序运行良好,当我更改某些内容时,它会显示此错误并且应用程序崩溃。但是,如果我保存相同的文件而不进行任何更改,它会刷新并正常工作。所以就像每次我保存它都会显示错误,而下次我保存文件时它就会消失。
我正在使用 expo go app 在我的物理设备上测试这个应用程序。
文件的确切代码是这样的:
import React, { useRef, useEffect, useState } from "react";
import { StyleSheet, Text, View, Dimensions, Pressable } from "react-native";
import { Video } from "expo-av";
/** config.js contains this values
export const theme = {
backgroundColor: "#f1f1f1",
fontColor: "#212121",
};
*/
import { theme } from "../config";
import { PanGestureHandler } from "react-native-gesture-handler";
import Animated, {
useAnimatedGestureHandler,
useAnimatedStyle,
useSharedValue,
withTiming,
interpolate,
runOnJS,
} from "react-native-reanimated";
import * as MediaLibrary from "expo-media-library";
const AnimatedVideo = Animated.createAnimatedComponent(Video);
const { width, height } = Dimensions.get("window");
const BAR_HEIGHT = 60;
const BREAK_POINT = 100;
const Videos = () => {
const video = useRef(null);
const [status, setStatus] = useState({});
// useEffect(() => {
// getVideos();
// }, []);
// const getVideos = async () => {
// try {
// const { status } = await MediaLibrary.requestPermissionsAsync();
// if (status === "granted") {
// const userVideos = await MediaLibrary.getAssetsAsync({
// first: 999,
// mediaType: MediaLibrary.MediaType.video,
// });
// }
// } catch (error) {
// console.log(error);
// }
// };
const translateY = useSharedValue(0);
const offsetY = useSharedValue(0);
const state = useSharedValue("down");
const onGestureEvent = useAnimatedGestureHandler({
onActive: ({ translationY }) => {
translateY.value = translationY + offsetY.value;
},
onEnd: ({ translationY, velocityY }) => {
const point = translationY + 0.2 * velocityY;
if (state.value === "down") {
if (point > 0) {
// Go down rather close the player
translateY.value = withTiming(BAR_HEIGHT);
offsetY.value = BAR_HEIGHT;
} else {
// Go up
translateY.value = withTiming(-(height - BAR_HEIGHT));
offsetY.value = -(height - BAR_HEIGHT);
state.value = "up";
}
} else if (state.value === "up") {
if (point > 0) {
// Go down
translateY.value = withTiming(0);
offsetY.value = 0;
state.value = "down";
} else {
// Go Full Screen
translateY.value = withTiming(-(height - BAR_HEIGHT));
offsetY.value = -(height - BAR_HEIGHT);
state.value = "full";
}
}
},
});
const videoContStyle = useAnimatedStyle(() => {
return {
width,
height,
backgroundColor: "white",
position: "absolute",
zIndex: 2,
top: 0,
transform: [{ translateY: height - BAR_HEIGHT + translateY.value }],
};
});
const playerContStyle = useAnimatedStyle(() => {
return {
height: interpolate(
translateY.value,
[-(height - BAR_HEIGHT), 0],
[225, BAR_HEIGHT]
),
width: "100%",
borderWidth: StyleSheet.hairlineWidth,
borderColor: "black",
};
});
const videoStyle = useAnimatedStyle(() => {
return {
width:
translateY.value < -BREAK_POINT
? "100%"
: interpolate(
translateY.value,
[-BREAK_POINT, 0],
[width, width / 2]
),
height: "100%",
};
});
return (
<View style={styles.container}>
<View style={styles.mainCont}>
<Pressable
onPress={() => {
translateY.value = withTiming(-(height - BAR_HEIGHT));
offsetY.value = -(height - BAR_HEIGHT);
state.value = "up";
}}
>
<Text>Go full screen</Text>
</Pressable>
</View>
<Animated.View style={videoContStyle}>
<View style={styles.gestureCont}>
<PanGestureHandler onGestureEvent={onGestureEvent}>
<Animated.View style={playerContStyle}>
<AnimatedVideo
ref={video}
style={videoStyle}
source={{
uri: "file:///storage/emulated/0/Download/bannerg004.mp4",
}}
useNativeControls={true}
resizeMode="cover"
onPlaybackStatusUpdate={(newstatus) => setStatus(newstatus)}
/>
</Animated.View>
</PanGestureHandler>
</View>
<Pressable
onPress={() => {
status.isPlaying
? video.current.pauseAsync()
: video.current.playAsync();
}}
>
<Text>{status.isPlaying ? "pause" : "Play"}</Text>
</Pressable>
</Animated.View>
</View>
);
};
export default Videos;
const styles = StyleSheet.create({
container: {
...StyleSheet.absoluteFillObject,
backgroundColor: theme.backgroundColor,
},
mainCont: {
width,
height,
},
videoCont: {
width,
height,
backgroundColor: "lightblue",
position: "absolute",
zIndex: 2,
top: 0,
transform: [{ translateY: height - BAR_HEIGHT }],
},
playerCont: {
height: BAR_HEIGHT,
width: "100%",
borderWidth: StyleSheet.hairlineWidth,
borderColor: "black",
},
});
平台详情:
- 世博SDK:40.0
- 安卓设备:三星galaxy j7 neo(物理设备)android 9.0
- 操作系统:Windows 7
我尝试了很多事情,例如:
- 从 PanGestureHandler 中删除 onGestureEvent 但有同样的问题。
- 从 AnimatedVideo 中删除 onPlaybackStatusUpdate 道具但有同样的问题。
我发现这个问题通常是由于 useEffect 钩子或由于链渲染而发生的。但没有一个对这个有效。
请,有人可以建议我做错了什么吗?
解决方案
对此的简单解决方案是使用包裹在 Video 组件周围的 Animated.View 组件来实现所需的动画样式。
但是我仍然没有运气找到真正的问题解决方案。
推荐阅读
- python - Metatrader 5 login() 更新后损坏?
- javascript - 如何使用 javascript 在 html 页面之间传递信息?
- python - 在树的右侧获取错误的祖先
- android - 如何获取用户在android中输入当前应用的应用信息页面的事件
- java - Heroku 部署 java .war 文件返回错误:spawn java ENOENT
- javascript - 更改目录时项目未运行
- powershell - 文件资源管理器不会显示 PowerShell 模块目录,否则在 $env:psmodulepath 中可见
- resteasy - Quarkus Resteasy 反应式多部分流
- php - php curl 在调试代理服务器(如提琴手)工作时不起作用
- docker - 无法访问 docker 容器内的 jupyterlab