【问题标题】:Warning: Cant perform React state update警告:无法执行 React 状态更新
【发布时间】:2020-01-09 21:34:09
【问题描述】:

我正在使用 Firebase 创建一个基本的登录/注销应用程序。当我启动应用程序并注册用户时,一切似乎都很好。但是当我注销并尝试注册第二个用户时,我会收到下面的黄色警告。我已经阅读了有关如何通过使用 isMounted() 来避免此警告的信息,但是我还没有让它工作,并且我读到 isMounted() 无论如何都已被弃用。请帮忙。谢谢!

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in %s.%s, the componentWillUnmount method, 
    in HomeScreen (at SceneView.js:9)
    in SceneView (at StackViewLayout.tsx:900)
    in RCTView (at createAnimatedComponent.js:151)
    in AnimatedComponent (at StackViewCard.tsx:106)
    in RCTView (at createAnimatedComponent.js:151)
    in AnimatedComponent (at screens.native.js:71)
    in Screen (at StackViewCard.tsx:93)
    in Card (at createPointerEventsContainer.tsx:95)
    in Container (at StackViewLayout.tsx:975)

从警告中,我相信我的问题出在下面的HomeScreen.js

import React from 'react';
import { Text, Button, View, StyleSheet, Image } from 'react-native'
import * as firebase from 'firebase';

export default class HomeScreen extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            name: "",
            email: ""
        }
    }
    static navigationOptions = {
        title: "Home",
        header: null
    }
    componentDidMount() {
        firebase.auth().onAuthStateChanged(authenticate => {
            if (authenticate) {
                this.setState({
                    email: authenticate.email,
                    name: authenticate.displayName
                });
            } else {
                this.props.navigation.replace("SignIn");
            }
        });
    }

    signOutUser = () => {
        firebase
            .auth()
            .signOut()
            .then(() => console.log("signout"))
            .catch(error => alert(error.message))
    }

    render() {
        return (
            <View style={styles.container}>
                <View style={styles.logoContainer}>
                    <Image source={require('../assets/logo.png')} />
                    <Text>Home Screen</Text>
                </View>
                <View>
                    <Text>Hey {this.state.name}</Text>
                    <Text>Logged in as {this.state.email}</Text>

                </View>
                <Button
                    style={styles.button}
                    title="Log Out"
                    full
                    rounded
                    success
                    onPress={() => {
                        this.signOutUser();
                    }}
                >
                    <Text style={styles.buttonText}>Sign Out</Text>
                </Button>
            </View >

        );
    }
}

再次感谢! -马特

【问题讨论】:

    标签: javascript react-native firebase-authentication


    【解决方案1】:

    您需要取消订阅 firebase 监听器,否则会导致此内存泄漏问题。

    import React from 'react';
    import { Text, Button, View, StyleSheet, Image } from 'react-native'
    import * as firebase from 'firebase';
    
    export default class HomeScreen extends React.Component {
        unsubscribeUserAuthStateChangedListener = null;
    
        constructor(props) {
            super(props);
            this.state = {
                name: "",
                email: ""
            }
        }
        static navigationOptions = {
            title: "Home",
            header: null
        }
        componentDidMount() {
            this.unsubscribeUserAuthStateChangedListener = firebase.auth().onAuthStateChanged(authenticate => {
                if (authenticate) {
                    this.setState({
                        email: authenticate.email,
                        name: authenticate.displayName
                    });
                } else {
                    this.props.navigation.replace("SignIn");
                }
            });
        }
    
        componentWillUnmount() {
          if (this.unsubscribeUserAuthStateChangedListener) {
            this.unsubscribeUserAuthStateChangedListener();
          }
        }
    
        signOutUser = () => {
            firebase
                .auth()
                .signOut()
                .then(() => console.log("signout"))
                .catch(error => alert(error.message))
        }
    
        render() {
            return (
                <View style={styles.container}>
                    <View style={styles.logoContainer}>
                        <Image source={require('../assets/logo.png')} />
                        <Text>Home Screen</Text>
                    </View>
                    <View>
                        <Text>Hey {this.state.name}</Text>
                        <Text>Logged in as {this.state.email}</Text>
    
                    </View>
                    <Button
                        style={styles.button}
                        title="Log Out"
                        full
                        rounded
                        success
                        onPress={() => {
                            this.signOutUser();
                        }}
                    >
                        <Text style={styles.buttonText}>Sign Out</Text>
                    </Button>
                </View >
    
            );
        }
    }
    

    【讨论】:

    • 谢谢。我最终使用了_isMounted,我相信它的行为方式与您建议的unsubscribeUserAuthStateChangedListener
    【解决方案2】:

    不言自明,就像 unmounted 的名字一样,当屏幕存在后调用 setState 时会发生这种情况。

    onAuthStateChanged 是一个监听器,可以随时调用, 我建议您自己控制它,并在设置状态之前检查屏幕是否已安装。

      constructor(props) {
                super(props);
                this.state = {
                    name: "",
                    email: "",
                    isMounted: true
                }
            }
    
    
    
    
        componentDidMount() {
                firebase.auth().onAuthStateChanged(authenticate => {
                    if (authenticate) {
                      if(this.state.isMounted) {
                        this.setState({
                            email: authenticate.email,
                            name: authenticate.displayName
                        });
                     }
                    } else {
                        this.props.navigation.replace("SignIn");
                    }
                });
            }
    
        componentwillUnMount() {
        this.setState({isMounted: false})
        }
    

    【讨论】:

    • 感谢您的帮助。不幸的是,我仍然遇到同样的问题。我再次运行 nmp start 并重新启动模拟器。同样的警告...
    猜你喜欢
    • 2021-02-24
    • 2021-03-27
    • 2019-09-11
    • 2021-08-07
    • 2020-06-14
    • 1970-01-01
    • 2021-12-03
    • 2021-11-15
    相关资源
    最近更新 更多