React Native / Expo - не удается выполнить обновление состояния React для отключенного компонента - PullRequest
0 голосов
/ 11 марта 2020

Я получаю сообщение об ошибке «Это не работает, но это указывает на утечку памяти в вашем приложении. Чтобы исправить, отмените все подписки и асинхронные задачи в% s.% S, функция очистки useEffect» при использовании React-родной и выставочный.

Я получаю это только при запуске симуляции iOS. Проект работает нормально при развертывании и на моем фактическом ios устройстве.

import React, { useState, useContext } from "react";
import { Text, View } from "react-native";

import { FirebaseContext } from "components/Firebase";

import SignIn from "./SignIn";
import SignUp from "./SignUp";
import ForgotPassword from "./ForgotPassword";
import Verify from "./Verify";

import styles from "./styles";

// Login page class component
const Login = () => {
    // initializing hooks
    const firebase = useContext(FirebaseContext);

    const [loading, setLoading] = useState(false);
    const [current, setCurrent] = useState("login");
    const [netid, setNetid] = useState("");
    const [password, setPassword] = useState("");
    const [secondPassword, setSecondPassword] = useState("");
    const [authError, setAuthError] = useState("");

    const [touched, setTouched] = useState({
        netid: false,
        password: false,
        secondPassword: false
    });

    // methods for handling the changing of active login function
    const moveTo = target => (() => {
        setTouched({
            netid: false,
            password: false,
            secondPassword: false
        });
        setCurrent(target);
        setPassword('');
        setSecondPassword('');
        setAuthError('');
    });

    // method for tracking input touch
    const handleTouch = field => e => {
        setTouched({ ...touched, [field]: true });
    };

    // makes sure netid doesn't have an invalid character
    // netids are alphanumeric only
    const hasInvalidChars = phrase => {
        const set =
            "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLM" +
            "NOPQRSTUVWXYZ1234567890";
        for (let i = 0; i < phrase.length; i++) {
            if (!set.includes(phrase[i])) {
                return true;
            }
        }
        return false;
    };

    // methods for input errors validation
    const validate = e => {
        return {
            netid: netid.length < 4 || hasInvalidChars(netid),
            password:
                password.length < 6 &&
                (current == "signUp" || current == "login"),
            secondPassword:
                secondPassword != password &&
                password.length > 5 &&
                current == "signUp"
        };
    };

    const errorMessage = (field, errors) => {
        switch (field) {
            case "netid": {
                return errors[field] && touched[field]
                    ? "Please, type a valid NetID (for example 'abc12')."
                    : "";
            }
            case "password": {
                return errors[field] && touched[field]
                    ? "Please, type a valid Password (at least 6 symbols)."
                    : "";
            }
            case "secondPassword": {
                return errors[field] && touched[field]
                    ? "Please, type a matching Password."
                    : "";
            }
        }
        return "";
    };

    // method for handling changes to inputs
    const changeHandler = (name, value) => {
        setAuthError("");
        const func = {
            netid: setNetid,
            password: setPassword,
            secondPassword: setSecondPassword
        }[name];
        func && func(value);
    };

    // method for handling submit - logic based on state
    const handleSubmit = async e => {
        setLoading(true);
        // continue through if fields aren't empty
        if (!netid.trim() && !password && current != "verification") {
            return;
        }

        let authorization = {
            login: firebase.signIn,
            signUp: firebase.signUp,
            forgot: firebase.resetPassword,
            verification: firebase.resendVerificationEmail
        }[current];


        // let error = await authorizationPromise;
        setLoading(false);
        authorization(netid.trim(), password, error => {
            if (error) {
                handleError(error);
                return;
            }
            moveTo('login')();
        })

    };

    // method for transcribing DB errors to user friendly ones
    const handleError = error => {
        switch (error.code) {
            case "auth/user-not-found": {
                setAuthError("User with this NetID was not found.");
                setPassword("");
                break;
            }
            case "auth/wrong-password": {
                setAuthError("The NetID or password is not correct.");
                setPassword("");
                break;
            }
            case "auth/email-already-in-use": {
                setAuthError("This NetID is already in use.");
                break;
            }
            case "auth/too-many-requests": {
                setAuthError("Too many requests. Please try again later.");
                break;
            }
            case "client/verification": {
                moveTo('verification')(); // Fake error created for unverified email detection
                break;
            }
            case "client/verification-email-sent": {
                setAuthError("Verification Email has been succesfully sent."); // Fake error created for email resend response
                break;
            }
            case "client/reset-email-sent": {
                setAuthError("Password Reset Email has been succesfully sent."); // Fake error created for email resend response
                break;
            }
        }
    };

    // assigning local boolean variables
    const login = (
        <SignIn
            loading={loading}
            netid={netid}
            password={password}
            handler={changeHandler}
            toSignUp={moveTo('signUp')}
            toForgot={moveTo('forgot')}
            submit={handleSubmit}
            handleTouch={handleTouch}
            touched={touched}
            validate={validate}
            errorMessage={errorMessage}
            authError={authError}
        />
    );

    const signUp = (
        <SignUp
            loading={loading}
            netid={netid}
            password={password}
            secondPassword={secondPassword}
            handler={changeHandler}
            toLogin={moveTo('login')}
            submit={handleSubmit}
            handleTouch={handleTouch}
            touched={touched}
            validate={validate}
            errorMessage={errorMessage}
            authError={authError}
        />
    );

    const forgot = (
        <ForgotPassword
            loading={loading}
            netid={netid}
            handler={changeHandler}
            toLogin={moveTo('login')}
            submit={handleSubmit}
            handleTouch={handleTouch}
            touched={touched}
            validate={validate}
            errorMessage={errorMessage}
            authResponse={authError}
        />
    );

    const verification = (
        <Verify
            loading={loading}
            toLogin={moveTo('login')}
            submit={handleSubmit}
            authResponse={authError}
        />
    );

    return (
        <View style={styles.PageContainer}>
            <Text style={styles.Logo}>FinalsClub</Text>
            {
                {
                    login,
                    signUp,
                    forgot,
                    verification
                }[current]
            }
        </View>
    );
};

export default Login;
...