javascript - 使用 React Native Navigation 时超出最大调用堆栈大小
我刚刚开始使用 React Native,所以我还在学习。
我正在尝试在我的应用中实现导航,几乎所有功能都正常,除了有一个页面。
在应用中,当用户注册时,他可以选择作为个人或作为组织注册,这将根据他的选择引导他进入不同的注册表单。
但是,当我选择任意一个选项时,应用会崩溃,并显示以下错误:
未捕获的错误:RangeError:已超出最大调用堆栈大小,堆栈。
我已经在网上寻找过答案,大多数情况下这是因为导航中存在无限循环。然而,我在代码中没有看到可能出现循环的地方,而且我像处理其他页面一样处理了它,而其他页面再次正常工作。
这是 App.js 的代码
import React from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { LinearGradient } from 'expo-linear-gradient';
import WelcomeToKarma from "./components/WelcomeToKarma.js";
import Login from "./components/Login.js";
import ForgotPass from "./components/ForgotPass.js";
import UserRegistration from "./components/UserRegistration.js";
import OpenEmail from "./components/OpenEmail.js";
function InitialScreen({ navigation }) {
return (
<View style={styles.container}>
<LinearGradient
style={{ alignItems: 'center', justifyContent: 'center', flex: 1, width: '100%' }}
colors={['#00c5c4', '#01a7a6']}
start={{ x: 1, y: 0 }}
end={{ x: 0, y: 0 }}>
<Text style={styles.textHeader}>KARMA</Text>
<Text style={styles.text}>Lorem ipsum dolo ecte </Text>
<Text style={styles.text}>adipisicing elit sed do</Text>
<TouchableOpacity
style={styles.buttonContainer}
onPress={() => navigation.navigate('Back')}
>
<Text style={{ color: "white", fontSize: 20, }}>Sign Up</Text>
</TouchableOpacity>
<Text
style={styles.loginText}
onPress={() => navigation.navigate('Loginate')}
>
Already have an account? Login
</Text>
</LinearGradient>
</View>
);
}
const Stack = createStackNavigator();
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={InitialScreen} options={{ headerShown: false }} />
<Stack.Screen name="Back" component={WelcomeToKarma} options={{ headerShown: false }} />
<Stack.Screen name="UserRegistration"
component={UserRegistration}
options={{
headerTintColor: '#01b0b0',
title: 'Sign up',
headerTitleStyle: {
textAlign: 'left',
fontWeight: 'bold',
fontSize: 22,
color: 'black',
}
}} />
<Stack.Screen name="Loginate" component={Login}
options={{
headerTintColor: '#01b0b0',
title: 'Login',
headerTitleStyle: {
textAlign: 'left',
color: 'black',
fontSize: 22,
}
}} />
<Stack.Screen name="ForgotPass" component={ForgotPass}
options={{
headerTintColor: '#01b0b0',
title: 'Forgot Password',
headerTitleStyle: {
textAlign: 'left',
color: 'black',
fontSize: 22,
}
}} />
<Stack.Screen name="OpenEmail" component={OpenEmail}
options={{
headerTintColor: '#01b0b0',
title: "Forgot Password",
headerTitleStyle: {
textAlign: 'left',
color: 'black',
fontSize: 22,
}
}} />
</Stack.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
textHeader: {
color: 'white',
fontSize: 80,
},
text: {
color: 'white',
fontSize: 20,
},
buttonContainer: {
borderColor: 'white',
borderWidth: 2,
borderRadius: 30,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
height: 44,
width: 200,
marginBottom: 20,
marginTop: 10,
position: 'absolute',
bottom: 60,
},
loginText: {
color: "white",
fontSize: 15,
marginTop: 10,
marginBottom: 20,
bottom: 10,
position: 'absolute',
justifyContent: 'center',
alignItems: 'center'
},
});
这是 WelcomeToKarma.js 的代码,用户可以在这里选择自己是个人还是组织。
import React, { Component } from 'react';
import { StyleSheet, Text, View, TouchableOpacity, ScrollView, SafeAreaView } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
import Constants from 'expo-constants';
import heart from '../assets/heart.png';
import earth from '../assets/earth.png';
import Card from './Card.js';
export default class WelcomeToKarma extends Component {
render() {
const { navigate } = this.props.navigation;
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={styles.container}>
<View style={styles.welcomeText}>
<Text style={styles.header}>Welcome to KARMA</Text>
<Text style={styles.text}>Lorem ipsum dolo sit amet, consectetur adip isicing elit, sed do eiusmod</Text>
</View>
<ScrollView
scrollEventThrottle={16}
horizontal={true}
showsHorizontalScrollIndicator={false}
style={styles.scrollViewView}>
<Card imageUri={heart} question="Are you an individual?" page="UserRegistration"></Card
{/* This is where the app crashes when I press the TouchableOpacity*/}
<Card imageUri={earth} question="Are you an organization?" page=""></Card>
{/* And here as well, I know the page parameter is empty, that's because I still haven't done the page for it */}
</ScrollView>
<View style={styles.bottomView}>
<Text style={styles.boldText}>Already on Karma?</Text>
<View style={styles.buttonView}>
<LinearGradient
style={{ borderRadius: 22, alignItems: 'center', justifyContent: 'center', flexDirection: 'row' }}
colors={['#00c5c4', '#01a7a6']}
start={{ x: 1, y: 0 }}
end={{ x: 0, y: 0 }}>
<TouchableOpacity
style={styles.loginButton}
onPress={() => navigate('Loginate')}
>
<Text style={styles.login}>Login</Text>
</TouchableOpacity>
</LinearGradient>
</View>
</View>
</View>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#F5F5F5',
marginTop: Constants.statusBarHeight,
alignItems: 'center',
justifyContent: 'center',
},
welcomeText: {
marginBottom: 10,
},
scrollViewView: {
alignItems: 'center',
pagingEnabled: 'true',
showPageIndicator: 'true',
marginBottom: 20,
},
bottomView: {
backgroundColor: 'white',
width: '100%',
marginHorizontal: 20,
paddingBottom: 30,
},
buttonView: {
backgroundColor: 'white',
alignItems: 'center',
width: '100%'
},
header: {
fontSize: 20,
marginHorizontal: 20,
marginVertical: 10,
textAlign: 'left'
},
text: {
fontSize: 15,
marginHorizontal: 20,
marginVertical: 10,
textAlign: 'left'
},
boldText: {
fontSize: 15,
marginHorizontal: 20,
marginVertical: 10,
textAlign: 'left',
fontWeight: 'bold'
},
loginButton: {
borderRadius: 22,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
height: 44,
width: '85%',
padding: 20,
backgroundColor: 'white',
margin: 2,
},
login: {
color: '#01b0b0',
textAlign: 'center',
fontSize: 20,
},
});
我基本上是想把 ToucheableOpacity onPress 作为参数传递给 Card。当我按这些按钮时,应用会崩溃。
这是 Card.js 的代码。
import React, { Component } from 'react';
import { StyleSheet, Text, View, TouchableOpacity, Image } from 'react-native';
import { LinearGradient } from 'expo-linear-gradient';
class Card extends Component {
constructor(props) {
super(props);
this.navigate.bind(this);
}
navigate(txt) {
this.navigate(txt);
}
render() {
return (
<View style={styles.container}>
<View style={{ justifyContent: 'space-between', alignItems: 'center', flex: 1 }}>
<Image source={this.props.imageUri} style={{ width: '50%', height: '50%', resizeMode: 'cover' }}></Image>
</View>
<View style={{ justifyContent: 'center', flex: 1 }}>
<Text style={{ marginVertical: 5, fontWeight: 'bold' }}>{this.props.question}</Text>
<Text style={{ marginVertical: 5 }}>Lorem ipsum dolor sit amet, consectetur adip isicing elit,
sed do eiusm ut labore et dolore magna aliqua
</Text>
<View>
<LinearGradient
style={styles.signupButtonView}
colors={['#00c5c4', '#01a7a6']}
start={{ x: 1, y: 0 }}
end={{ x: 0, y: 0 }}
>
<TouchableOpacity
onPress={() => this.navigate(this.props.page)}>
<Text style={styles.signup} >Sign up</Text>
</TouchableOpacity>
</LinearGradient>
</View>
</View>
</View>
)
}
}
export default Card;
const styles = StyleSheet.create({
container: {
height: '95%',
width: 250,
borderRadius: 20,
borderBottomWidth: 10,
borderBottomColor: '#01b0b0',
marginHorizontal: 10,
marginVertical: 10,
shadowColor: 'black',
shadowOffset: { width: 0, height: 3 },
shadowRadius: 6,
shadowOpacity: 0.26,
elevation: 8,
padding: 20,
backgroundColor: 'white'
},
signupButtonView: {
borderRadius: 22,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
padding: 20,
height: 44,
width: 200,
},
signupButton: {
borderRadius: 22,
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'row',
padding: 20,
height: 44,
width: 200,
},
signup: {
color: 'white',
fontSize: 20,
},
sty: {
borderRadius: 30,
}
});
导航在其他页面都能正常工作,所以我不明白为什么它在这个页面上不行。会不会是因为我没有正确传递 ToucheableOpacity onPress 方法?我尝试过不同的方式将 onPress 作为参数传递,但看起来这种方式是最好的方式(如果不是唯一的方式的话?)
我也愿意接受任何改善我编码的建议,正如我所说:我刚开始学习 React Native。
答案#1
这看起来非常递归:
navigate(txt) {
this.navigate(txt);
}
你已经将 navigate 绑定到类。你在函数 navigate 内部,而里面的那一行正在调用它自己。你会得到一个 stackover.com
你需要像在 'WelcomeToKarma' 中那样,在 'Card' 中获取导航属性,并使用它来导航。
const { navigate } = this.props.navigation;
所以导航可能会变成
navigate(txt) {
this.props.navigate(txt);
}
问题解决了!
