Предупреждение после регистрации и входа в систему в ReactJS

# #reactjs #firebase-authentication

Вопрос:

Поскольку я новичок в ReactJS, я не могу понять, почему я получаю это «Предупреждение: Не удается выполнить обновление состояния реакции для размонтированного компонента. Это не операция, но это указывает на утечку памяти в вашем приложении. Чтобы исправить это, отмените все подписки и асинхронные задачи в функции очистки useEffect». после регистрации и входа в систему. Вот мой код следующим образом:

AuthContext.js:

 import React, { useContext, useState, useEffect } from "react";
import { auth } from "../firebase";

const AuthContext = React.createContext();

export function useAuth() {
  return useContext(AuthContext);
}

export function AuthProvider({ children }) {
  const [currentUser, setCurrentUser] = useState();
  const [loading, setLoading] = useState(true);

  function signup(email, password) {
    return auth.createUserWithEmailAndPassword(email, password);
  }

  function login(email, password) {
    return auth.signInWithEmailAndPassword(email, password);
  }

  useEffect(() => {
    const unsubscribe = auth.onAuthStateChanged((user) => {
      setCurrentUser(user);
      setLoading(false);
    });

    return unsubscribe;
  }, []);

  const value = {
    currentUser,
    login,
    signup,
  };

  return (
    <AuthContext.Provider value={value}>
      {!loading amp;amp; children}
    </AuthContext.Provider>
  );
}
 

Signup.js:

 import React, { useRef, useState } from "react";
import { useAuth } from "../contexts/AuthContext";
import { Link, useHistory } from "react-router-dom";

export default function Signup() {
  const emailRef = useRef();
  const passwordRef = useRef();
  const passwordConfirmRef = useRef();
  const { signup } = useAuth();
  const [error, setError] = useState("");
  const [loading, setLoading] = useState(false);
  const history = useHistory();

  async function handleSubmit(e) {
    e.preventDefault();

    if (passwordRef.current.value !== passwordConfirmRef.current.value) {
      return setError("Passwords do not match");
    }

    try {
      setError("");
      setLoading(true);
      await signup(emailRef.current.value, passwordRef.current.value);
      history.push("/login");
    } catch (e) {
      console.error(e);
    }
    setLoading(false);
  }

  return (
    <div>
      <div
        className="h-screen overflow-hidden flex 
        items-center justify-center bg-blue-300"
      >
        <form
          onSubmit={handleSubmit}
          className="space-y-5 bg-white p-16 rounded shadow w-2/3"
        >
          <h2 className="text-3xl mb-5 text-center text-gray-800">Sign Up</h2>
          <hr />

          <div class="bg-teal-200 relative text-teal-600 py-3 px-3 rounded-lg">
            {error}
          </div>

          <label
            htmlFor="email"
            className="block mb-1 font-mono mt-3 text-gray-500"
          >
            Email
          </label>
          <input
            ref={emailRef}
            type="email"
            name="email"
            placeholder="Email"
            className="w-full border-2 border-gray-200 p-3 
            rounded outline-none focus:border-blue-300"
            required
          />

          <label
            htmlFor="password"
            className="block mb-1 font-mono mt-3 text-gray-500"
          >
            Password
          </label>
          <input
            ref={passwordRef}
            type="password"
            name="password"
            placeholder="Password"
            className="w-full border-2 border-gray-200 p-3 
            rounded outline-none focus:border-blue-300"
            required
          />

          <label
            htmlFor="confirm password"
            className="block mb-1 font-mono mt-3 text-gray-500"
          >
            Confirm Password
          </label>
          <input
            ref={passwordConfirmRef}
            type="password"
            name="confirm-password"
            placeholder="Retype Password"
            className="w-full border-2 border-gray-200 p-3 
            rounded outline-none focus:border-blue-300"
            required
          />
          <hr />
          <button
            disabled={loading}
            type="submit"
            className="block w-full bg-pink-400 hover:bg-pink-300 p-4 
            rounded text-blck transition duration-300 font-semibold"
          >
            SIGN UP
          </button>
          <div className="w-100 text-center mt-2">
            Already have an account?{" "}
            <Link className="text-blue-600" to="/login">
              Log In
            </Link>
          </div>
        </form>
      </div>
    </div>
  );
}
 

Login.js:

 import React, { useRef, useState } from "react";
import { useAuth } from "../contexts/AuthContext";
import { Link, useHistory } from "react-router-dom";

export default function Login() {
  const emailRef = useRef();
  const passwordRef = useRef();
  const { login } = useAuth();
  const [error, setError] = useState("");
  const [loading, setLoading] = useState(false);
  const history = useHistory();

  async function handleSubmit(e) {
    e.preventDefault();

    try {
      setError("");
      setLoading(true);
      await login(emailRef.current.value, passwordRef.current.value);
      history.push("/appointments");
    } catch (e) {
      console.error(e);
    }
    setLoading(false);
  }

  return (
    <div>
      <div
        className="h-screen overflow-hidden flex 
      items-center justify-center bg-blue-300"
      >
        <form
          onSubmit={handleSubmit}
          className="space-y-5 bg-white p-16 rounded shadow w-2/3"
        >
          <h2 className="text-3xl mb-5 text-center text-gray-800">Log In</h2>
          <hr />

          <div class="bg-teal-200 relative text-teal-600 py-3 px-3 rounded-lg">
            {error}
          </div>

          <label
            htmlFor="email"
            className="block mb-1 font-mono mt-3 text-gray-500"
          >
            Email
          </label>
          <input
            ref={emailRef}
            type="email"
            name="email"
            placeholder="Email"
            className="w-full border-2 border-gray-200 p-3 
          rounded outline-none focus:border-blue-300"
          />

          <label
            htmlFor="password"
            className="block mb-1 font-mono mt-3 text-gray-500"
          >
            Password
          </label>
          <input
            ref={passwordRef}
            type="password"
            name="password"
            placeholder="Password"
            className="w-full border-2 border-gray-200 p-3 
          rounded outline-none focus:border-blue-300"
          />
          <button
            disabled={loading}
            type="submit"
            className="block w-full bg-pink-400 hover:bg-pink-300 p-4 
          rounded text-blck transition duration-300 font-semibold"
          >
            LOG IN
          </button>
          <div className="w-100 text-center mt-2">
            Need an account?{" "}
            <Link className="text-blue-500" to="/register">
              Sign Up
            </Link>
          </div>
        </form>
      </div>
    </div>
  );
}
 

Ответ №1:

Просто потому, что вы не сделали обратный вызов после возврата в useEffet, что означает, что ваш крючок useEffect должен быть таким:

 useEffect(() => {
 const unsubscribe = auth.onAuthStateChanged((user) => {
   if (user) {
       setCurrentUser(user);
   }

   setLoading(false);
 });

 return () => unsubscribe();
}, []);
 

Комментарии:

1. Он все еще дает то же самое предупреждение

2. @bhuvana проблема в том, что вы обновляете состояние во время размонтирования компонента, что не подходит для вашего компонента, пожалуйста, внесите изменения в свой код и удалите логику, которой вы можете избежать(обновите состояние, когда компонент размонтирован, я имею в виду в функции возврата крючка useEffect).