如何使用Firebase Auth的useEffect清理功能取消所有订阅和异步任务

时间:2020-08-08 20:49:00

标签: reactjs react-native react-hooks

我正在使用Firebase Auth处理React本机应用程序中的用户注册,登录和注销。我正在使用以下registerUser函数:

export const registerUser = async ({ name, email, password }) => {
  try {
    await firebase.auth().createUserWithEmailAndPassword(email, password);
    firebase.auth().currentUser.updateProfile({
      displayName: name
    });

    return {};
  } catch (error) {
    switch (error.code) {
      case "auth/email-already-in-use":
        return {
          error: "E-mail address is already in use."
        };
      case "auth/weak-password":
        return {
          error: "Password is too weak."
        };
      case "auth/too-many-requests":
        return {
          error: "Too many requests. Try again in a minute."
        };
      default:
        return {
          error: "Check your internet connection."
        };
    }
  }
};

我在RegisterScreen函数的帮助下在handleRegister中调用,该函数在用户提交表单时调用:

const handleRegister = async (values) => {
        if (loading) return;
        setLoading(true);
        const response = await registerUser({
            name: values.name,
            email: values.email,
            password: values.password
        });
        if (response.error) {
            Alert.alert('Error', response.error);
        }
        setLoading(false);
    };

注册有效,但出现以下警告:

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, a useEffect cleanup function,

有人可以告诉我如何使用useEffect删除此警告吗?

更新8/11/2020

我正在加载屏幕中初始化firebase,并尝试监听here中所述的身份验证状态。但是现在我得到了另一个警告:“警告:无法在现有状态转换期间(例如在'render'中)进行更新。呈现方法应该只是props和state的函数。”

const LoadingScreen = props => {
    const [initializing, setInitializing] = useState(true);
    const [user, setUser] = useState();

    if (!firebase.apps.length) {
        firebase.initializeApp(firebaseConfig);
    }

    const onAuthStateChanged = (user) => {
        setUser(user);
        if (initializing) setInitializing(false);
    }

    useEffect(() => {
        const subscriber = firebase.auth().onAuthStateChanged(onAuthStateChanged);
        return subscriber;
    }, []);

    if (initializing) return null;

    if (!user) {
        props.navigation.navigate('Auth');
    } else {
        props.navigation.navigate('App');
    }

    return (
        <View style={styles.screen}>
            <ActivityIndicator size='large' color={Colors.primaryColor} />
        </View>
    );
}

1 个答案:

答案 0 :(得分:0)

我的Firebase设置与您的设置不同,但是从您的LoadingScreen代码来看,您似乎应该调用函数来初始化Firebase并在useEffect挂钩中进行导航。也许尝试这样的事情?

const LoadingScreen = props => {
    const [initializing, setInitializing] = useState(true);
    const [user, setUser] = useState();

    useEffect(() => {
      if (!user) {
        props.navigation.navigate('Auth');
      } else {
        props.navigation.navigate('App');
      }
      }, [user])

    const onAuthStateChanged = (user) => {
        setUser(user);
        if (initializing) setInitializing(false);
    }

    useEffect(() => {
        // Run once, on mount
        if (!firebase.apps.length) {
          firebase.initializeApp(firebaseConfig);
        }

        const subscriber = firebase.auth().onAuthStateChanged(onAuthStateChanged);
        return subscriber;
    }, []);

    if (initializing) return null;

    return (
        <View style={styles.screen}>
            <ActivityIndicator size='large' color={Colors.primaryColor} />
        </View>
    );
}