首页 > 解决方案 > React Native - 未安装的组件

问题描述

我无法理解此错误的来源。控制台说:

无法对未安装的组件执行 React 状态更新。这是一个空操作,但它表明您的应用程序中存在内存泄漏。要解决此问题,请在 LoginScreen 的 componentWillUnmount 方法中取消所有订阅和异步任务。

我用 _isMounted 尝试了这个技巧 - 不起作用。

export default class LoginScreen extends React.Component {
    _isMounted = false;
    constructor(props) {
        super(props);
        this.state = {
            email: "",
            password: "",
            errorMessage: null,
            logOut: false,
        };
        this.handleLogin = this.handleLogin.bind(this);
    }

    componentDidMount() {
        this._isMounted = true;
    }

    componentWillUnmount() {
        this._isMounted = false;
    }

    handleLogin() {
        if (this._isMounted) {
            const { email, password } = this.state;
            firebase.auth().signInWithEmailAndPassword(email, password)
              .catch(errorMessage => this.setState({errorMessage}));

            this.props.navigation.navigate("Direction", { email, password });
        }
    };

    render() {
        return (
            <View style={styles.container}>
                <Text style={styles.greeting}>
                    Log in
                </Text>

                <View style={styles.form}>
                    <View>
                        <Text style={styles.inputTitle}>
                            Email
                        </Text>
                        <TextInput style={styles.input}
                                   autoCapitalize="none"
                                   onChangeText={ email => this.setState({email})}
                                   value={this.state.email}>
                        </TextInput>
                    </View>

                    <View>
                        <Text style={styles.inputTitle}>
                            Password
                        </Text>
                        <TextInput style={styles.input}
                                   secureTextEntry
                                   autoCapitalize="none"
                                   onChangeText={password => this.setState({password})}
                                   value={this.state.password}>
                        </TextInput>
                    </View>

                    <Text style={styles.error}>
                        { this.state.errorMessage &&
                            <Text style={styles.error}>
                                Incorrect login or password
                            </Text>
                        }
                    </Text>

                    <TouchableOpacity style={styles.button}
                                      onPress={this.handleLogin}>
                    <Text style={styles.inputTitle}>
                        Log in
                    </Text>
                    </TouchableOpacity>

                    <View style={styles.register}>
                        <Text style={{color: "grey"}}>
                            Don't have an Account
                        </Text>
                        <TouchableOpacity style={styles.secondButton}
                                          onPress={() => { this.props.navigation.navigate("Register")}}>
                            <Text style={styles.inputTitle}>
                                Registration
                            </Text>
                        </TouchableOpacity>
                    </View>
                </View>
            </View>
        )
    }
}

标签: reactjsreact-nativenavigation

解决方案


我相信问题出在你的handleLogin方法上,主要的问题是signInWithEmailAndPassword返回一个承诺。这意味着流程如下:

  1. 用户按下登录按钮,并被handleLogin执行。
  2. 此时组件仍处于安装状态,因此流将进入if (this._isMounted)
  3. signInWithEmailAndPassword返回一个promise,所以如果有错误,catch 块不会立即执行。
  4. 然后,您离开当前组件,导致组件被卸载。
  5. signInWithEmailAndPassword 现在的 catch 块被执行(如果有错误),它尝试更新此时已卸载的组件的状态 -> 繁荣,您看到的控制台警告。

根据您要进行的流程,您可以通过将导航置于then如下块中来解决此问题,如下signInWithEmailAndPassword所示:

firebase.auth().signInWithEmailAndPassword(email, password)
               .then(() => this.props.navigation.navigate("Direction", { email, password }))
               .catch(errorMessage => this.setState({errorMessage}));

但请注意,这意味着您不会在出现错误的情况下离开。


推荐阅读