【问题标题】:React Native - unmounted componentReact Native - 未安装的组件
【发布时间】:2020-05-10 16:19:24
【问题描述】:

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

无法对未安装的组件执行 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>
        )
    }
}

【问题讨论】:

    标签: reactjs react-native navigation


    【解决方案1】:

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

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

    根据您要进行的流程,您可能可以通过将导航置于then 块中,跟在signInWithEmailAndPassword 后面,如下所示:

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

    但请注意,这意味着您不会在出现错误时离开。

    【讨论】:

      猜你喜欢
      • 2016-10-01
      • 2016-02-22
      • 2021-09-17
      • 1970-01-01
      • 1970-01-01
      • 2021-11-30
      • 2020-09-03
      • 1970-01-01
      • 2022-01-18
      相关资源
      最近更新 更多