首页 > 解决方案 > 无法从反应原生的子类堆栈导航器更新父类状态

问题描述

父类:

  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 传递给子类并控制父类状态。

标签: react-native

解决方案


您不能直接从导航器根向子组件传递事件。根据您计算出的父类和导航器根的模式,您必须在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>

推荐阅读