react-native - 无法从反应原生的子类堆栈导航器更新父类状态
问题描述
父类:
import React, { Component } from 'react';
import {
View,
Text,
StatusBar
} from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import LoginScreen from './AuthScreens/LoginScreen';
import RegisterScreen from './AuthScreens/RegisterScreen';
import HomeScreen from './HomeScreen/HomeScreen';
import themeStyle from './themes/theme.style';
const Stack = createStackNavigator();
class App extends Component {
constructor(props){
super(props);
this.toggleLoginState = this.toggleLoginState.bind(this);
this.state = {
isLogin:false
}
}
toggleLoginState() {
// this.setState({
// isLogin: true
// });
alert("toggling login status");
}
render(navigation) {
if(this.state.isLogin){
return(
<HomeScreen />
);
}
else {
return(
<NavigationContainer>
<StatusBar barStyle="light-content" backgroundColor={themeStyle.PRIMARY_COLOR_DARK}/>
<Stack.Navigator initialRouteName="Login"
screenOptions={{
headerShown: false
}}>
<Stack.Screen name="Login" component={LoginScreen} toggleLoginState={this.toggleLoginState}/>
<Stack.Screen name="Register" component={RegisterScreen} toggleLoginState={this.toggleLoginState}/>
</Stack.Navigator>
</NavigationContainer>
);
}
}
}
module.exports = App;
子班:
import React, { Component, useState } from 'react';
import {
Text,
View,
Image,
StyleSheet,
TextInput,
TouchableOpacity
} from 'react-native';
import theme from '../themes/theme.style';
import Feather from 'react-native-vector-icons/Feather';
class LoginScreen extends Component {
constructor(props){
super(props);
this.state = {
isUserBoxFocused : false,
isPassBoxFocused : false
};
}
userBoxHandler = () => {
if(isUserBoxFocused){
this.setState({
isUserBoxFocused : false
});
}
else{
this.setState({
isUserBoxFocused : true
});
}
}
passBoxHandler = () => {
if(isPassBoxFocused){
this.setState({
isPassBoxFocused : false
});
}
else{
this.setState({
isPassBoxFocused : true
});
}
}
alertBox = () => {
alert("login status toggling from login");
}
render(){
return (
<View style={styles.container}>
<View
style={styles.header}
>
<Image
style={{width:200,height:200}}
source={require('../images/profile.png')}
/>
<Text style={styles.welcome}>
Welcome!
</Text>
<Text style={styles.desc}>
Sign In to Continue
</Text>
</View>
<View style={styles.footer}>
<View style={styles.inputBox}>
<View style={styles.row}>
<Feather name="user" size={20}
color={this.state.isUserBoxFocused?theme.PRIMARY_COLOR_MED:theme.PRIMARY_COLOR_DARK}
/>
<TextInput
style={styles.input}
placeholder={'username or email'}
onFocus={() => userBoxHandler()}
onBlur={() => userBoxHandler()}
/>
</View>
<View style={{height:1,backgroundColor:'gray'}}/>
<View style={styles.row}>
<Feather
name="lock" size={20}
color={this.state.isPassBoxFocused?theme.PRIMARY_COLOR_MED:theme.PRIMARY_COLOR_DARK}
/>
<TextInput
style={styles.input}
placeholder={'paasword'}
onFocus={() => passBoxHandler()}
onBlur={() => passBoxHandler()}
/>
</View>
</View>
<TouchableOpacity style={styles.signInButton}
// onPress = {() => navigation.navigate('BaseScreen')}
onPress = {this.props.toggleLoginState}
>
<Text style={styles.signInText}>SIGN IN</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {navigation.navigate("Register")}}
>
<Text style={styles.registerHere}>
Not a User? <Text style={{fontWeight:'bold'}}>Register here</Text>
</Text>
</TouchableOpacity>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container :{
height:'100%',
flex:1,
backgroundColor:'white',
},
header : {
flex:1,
justifyContent:'center',
alignItems:'center',
// backgroundColor:'red'
},
footer : {
// backgroundColor:'blue',
flex:1,
justifyContent:'flex-end',
paddingVertical:40,
paddingHorizontal:40
},
welcome : {
fontSize:50,
fontWeight:'bold',
marginBottom:10,
color:theme.PRIMARY_COLOR_DARK
},
desc : {
fontSize:18,
color:theme.SECONDARY_COLOR_DARK
},
inputBox : {
backgroundColor:theme.BACKGROUND_COLOR_LIGHT,
borderColor:theme.PRIMARY_COLOR_DARK,
borderWidth:1,
borderRadius:10,
marginBottom:30
// padding:10
},
row : {
flexDirection:'row',
padding:10,
alignItems:'center',
},
input : {
padding:10,
flex:1,
// backgroundColor:'blue'
},
signInButton : {
backgroundColor:theme.SECONDARY_COLOR_DARK,
borderRadius:10,
padding:15,
alignItems:'center',
marginBottom:25
},
signInText : {
fontSize:25,
fontWeight:'bold',
color:'white'
},
registerHere : {
fontSize:15,
alignSelf:'center',
marginBottom:20,
color:theme.PRIMARY_COLOR_DARK
}
});
module.exports = LoginScreen;
我想创建一个登录流程。当用户从登录屏幕登录时,它将直接切换到 HomeScreen。为此,我尝试将父类中的状态用作“isLogin”,并希望从 LoginActivity 类中切换此状态。但是无法这样做,在 LoginScreen 中单击登录按钮时没有任何反应。我试图将 toggleLoginState 传递给子类并控制父类状态。
解决方案
您不能直接从导航器根向子组件传递事件。根据您计算出的父类和导航器根的模式,您必须在initialParams
内部使用属性Stack.Screen
。此属性接受一个对象,然后您必须将您的事件作为对象传递。
然后改变你的代码
<Stack.Screen name="Login" component={LoginScreen} toggleLoginState={this.toggleLoginState}/>
<Stack.Screen name="Register" component={RegisterScreen} toggleLoginState={this.toggleLoginState}/>
至
<Stack.Screen name="Login" component={LoginScreen} initialParams={{toggleLoginState : this.toggleLoginState}}/>
<Stack.Screen name="Register" component={RegisterScreen} initialParams={{toggleLoginState : this.toggleLoginState}}/>
route.params
在子组件中,必须使用child访问绑定到参数props
的事件,并使用用于将事件设置为对象的属性调用事件initialParams
。
loginEventHandler (){
const {route} = this.props;
route.params.toggleLoginState();
}
然后在登录按钮触发时调用它。
<TouchableOpacity style={styles.signInButton} onPress = {this.loginEventHandler}>
<Text style={styles.signInText}>SIGN IN</Text>
</TouchableOpacity>
推荐阅读
- sql - 使用单个查询更新并插入表中
- android - Algolia 的 xml 的“属性”引发编译错误
- javascript - 如何将 Firebase Callables 与 PWA 离线功能结合使用?
- python - 如何在某个未知索引处对字符串输入进行切片
- module - 禁用模块后,Magento2 模块字段在管理员中仍然可见
- powershell - 如何在 Powershell 中使用 OCSP 地址测试证书验证
- pdf - convertapi pdf to image:指定页面范围
- react-native - 什么是 React-Native 中的指针事件
- esp8266 - 最后的固件版本无法连接
- vue.js - 如何使用 ramda 和 vue 对过滤后的数据进行分页