Firebase Auth, React JS, ошибка: «logIn не является функцией»

FirebaseConfig.js

// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAnalytics } from "firebase/analytics";
import { getAuth } from "firebase/auth";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries

// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
  apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
  authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
  databaseURL: process.env.REACT_APP_FIREBASE_DATABASE_URL,
  projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
  storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.REACT_APP_FIREBASE_APP_ID,
  measurementId: process.env.REACT_APP_FIREBASE_MEASUREMENT_ID,
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);
export const analytics = getAnalytics(app);
export const auth = getAuth(app);

export default app;

AuthContext.js

import { createContext, useContext, useEffect, useState } from "react";
import {
  signInWithEmailAndPassword,
  signOut,
  onAuthStateChanged,
} from "firebase/auth";
import { auth } from "../firebaseConfig";

const AuthContext = createContext();

export const AuthContextProvider = ({ children }) => {
  const [user, setUser] = useState({});
  const logIn = (email, password) => {
    return signInWithEmailAndPassword(auth, email, password);
  };
  const logOut = () => {
    return signOut(auth);
  };
  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (currentUser) => {
      console.info(currentUser);
      setUser(currentUser);
    });
    return () => {
      unsubscribe();
    };
  }, []);
  return (
    <AuthContext.Provider value = {{ user, logIn, logOut }}>
      {children}
    </AuthContext.Provider>
  );
};

export const UserAuth = () => {
  return useContext(AuthContext);
};

Login.jsx (здесь появляется ошибка)

import React, { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import { UserAuth } from "../context/AuthContext";

const Login = () => {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [error, setError] = useState("");
  const navigate = useNavigate();
  const { logIn } = UserAuth() | {};

  const handleSubmit = async (e) => {
    e.preventDefault();
    setError("");
    try {
      await logIn(email, password);
      navigate("/account");
    } catch (e) {
      setError(e.message); // <--- This is the line where the error happens
      console.info(e.message);
    }
  };

  return (
    <div className = "max-w-[600px] mx-auto my-16 p-4">
      <div>
        <h1 className = "text-2xl font-bold py-2">Login to your Account</h1>
      </div>
      <form onSubmit = {handleSubmit}>
        <div className = "flex flex-col py-2">
          <label className = "py-2 font-medium">Email Address</label>
          <input
            input
            onChange = {(e) => setEmail(e.target.value)}
            className = "border p-2"
            type = "email"
          />
        </div>
        <div className = "flex flex-col py-2">
          <label className = "py-2 font-medium">Password</label>
          <input
            onChange = {(e) => setPassword(e.target.value)}
            className = "border p-2"
            type = "password"
          />
        </div>
        <button className = "border border-blue-500 bg-blue-600 hover:bg-blue-500 w-full p-4 my-12 text-white">
          Log In
        </button>
      </form>
    </div>
  );
};

export default Login;

пакет.json

{
  "name": "sa_react_firebase_database",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.17.0",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "dotenv": "^16.4.5",
    "firebase": "^10.12.2",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-router-dom": "^6.23.1",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "autoprefixer": "^10.4.19",
    "postcss": "^8.4.38",
    "tailwindcss": "^3.4.4"
  }
}

Я использую React JS и Firebase Auth, чтобы попытаться создать простую систему аутентификации электронной почты, следуя видеоруководству здесь:

https://thewikihow.com/video_x62aBvnRCKw?si=YGSjcsdjz5Zsb6Y-

Однако я получаю сообщение об ошибке: «logIn не является функцией», что является ошибкой перехвата в handleSubmit в Login.jsx. Я попытался клонировать репозиторий из GitHub загрузчика видео, и их код работает нормально, несмотря на отсутствие логических различий в handleSubmit, поэтому я подозреваю, что проблема в другом.

Перед отправкой я просматривал похожие сообщения, но обнаружил, что ответы были либо расплывчатыми, либо не могли ответить на вопрос, заданный в этих сообщениях.

Надеюсь, мы сможем получить здесь некоторые конкретные ответы, чтобы будущим людям, которые будут использовать Google по этой проблеме, было легче настроить систему аутентификации Firebase.

Обновлено: Спасибо за ответ, проблема решена! Сначала я позволил «logIn» вернуть неопределенное значение, чтобы деструктуризация не завершилась неудачей, но это заставило React думать, что это не функция. Обертывание App.js в «AuthContextProvider» и последующее удаление неопределенного значения из «logIn» устранило проблему!

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
65
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Эта ошибка обычно возникает по одной из следующих причин:

Функция входа в систему предоставлена ​​неправильно или недоступна из AuthContext. Поставщик AuthContext не оборачивает компонент входа в систему, поэтому компонент входа не имеет доступа к функции входа в систему. При использовании функции входа в систему может возникнуть опечатка или проблема с синтаксисом.

Пошаговое решение

  1. Убедитесь, что AuthContextProvider обертывает ваше приложение

AuthContextProvider должен охватывать компоненты, которым необходим доступ к функции входа в систему. Обычно вы помещаете все приложение или, по крайней мере, компоненты, требующие аутентификации, в AuthContextProvider.

Пример в App.js:

import React from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import { AuthContextProvider } from './context/AuthContext';
import Login from './components/Login';
import Account from './components/Account'; // Example account page

function App() {
  return (
    <AuthContextProvider>
      <Router>
        <Routes>
          <Route path = "/login" element = {<Login />} />
          <Route path = "/account" element = {<Account />} /> {/* Example route */}
        </Routes>
      </Router>
    </AuthContextProvider>
  );
}

export default App;

В этой настройке AuthContextProvider оборачивает маршрутизатор, гарантируя, что все маршруты, включая вход в систему, имеют доступ к контексту.

  1. Проверка использования функции UserAuth в Login.jsx

Убедитесь, что вы правильно используете перехватчик UserAuth для доступа к функции входа в систему из контекста. {logIn} = UserAuth() || {} гарантирует, что даже если UserAuth вернет неопределенное значение, деструктуризация не завершится неудачей.

Пример в Login.jsx:

import React, { useState } from 'react';
import { Link, useNavigate } from 'react-router-dom';
import { UserAuth } from '../context/AuthContext';

const Login = () => {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [error, setError] = useState("");
  const navigate = useNavigate();
  const { logIn } = UserAuth() || {};  // Ensures logIn is safely destructured

  const handleSubmit = async (e) => {
    e.preventDefault();
    setError("");
    try {
      await logIn(email, password);
      navigate("/account");
    } catch (e) {
      setError(e.message);
      console.info(e.message);
    }
  };

  return (
    <div className = "max-w-[600px] mx-auto my-16 p-4">
      <div>
        <h1 className = "text-2xl font-bold py-2">Login to your Account</h1>
      </div>
      <form onSubmit = {handleSubmit}>
        <div className = "flex flex-col py-2">
          <label className = "py-2 font-medium">Email Address</label>
          <input
            onChange = {(e) => setEmail(e.target.value)}
            className = "border p-2"
            type = "email"
          />
        </div>
        <div className = "flex flex-col py-2">
          <label className = "py-2 font-medium">Password</label>
          <input
            onChange = {(e) => setPassword(e.target.value)}
            className = "border p-2"
            type = "password"
          />
        </div>
        <button className = "border border-blue-500 bg-blue-600 hover:bg-blue-500 w-full p-4 my-12 text-white">
          Log In
        </button>
      </form>
    </div>
  );
};

export default Login;
  1. Отладка инициализации AuthContext

Убедитесь, что AuthContext и функции, представленные в нем (logIn и logOut), правильно определены и не исключены по ошибке. Также убедитесь, что аутентификация правильно импортирована из firebaseConfig.js.

Пример AuthContext.js:

import { createContext, useContext, useEffect, useState } from "react";
import {
  signInWithEmailAndPassword,
  signOut,
  onAuthStateChanged,
} from "firebase/auth";
import { auth } from "../firebaseConfig";

const AuthContext = createContext();

export const AuthContextProvider = ({ children }) => {
  const [user, setUser] = useState({});
  
  const logIn = (email, password) => {
    return signInWithEmailAndPassword(auth, email, password);
  };

  const logOut = () => {
    return signOut(auth);
  };

  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, (currentUser) => {
      setUser(currentUser);
    });
    return () => {
      unsubscribe();
    };
  }, []);

  return (
    <AuthContext.Provider value = {{ user, logIn, logOut }}>
      {children}
    </AuthContext.Provider>
  );
};

export const UserAuth = () => {
  return useContext(AuthContext);
};

Я надеюсь, что это помогает

Проблема решена, спасибо! Комбинация Решения 1+2 была тем ответом, который я искал. Сначала я позволил «logIn» вернуть неопределенное значение, чтобы деструктуризация не завершилась неудачей, но это заставило React думать, что это не функция. Обертывание App.js в <AuthContextProvider> и последующее удаление неопределенного значения из «logIn» устранило проблему! Решение 3 ни на что не повлияло, так как я тщательно проверил отсутствие орфографических ошибок.

LimeBunnyDev 15.06.2024 10:41

В. App.js, я оборачиваю AuthProvider, который является контекстом... вокруг всей маршрутизации.

const App = () => {
 const routing = useRoutes(Themeroutes);

    // Warp with <AuthProvider> to make Context works
        return (
          <AuthProvider>
          <div className = "dark">{routing}</div>
           </AuthProvider>
           );
         };

Этот AuthProvider взят из AuthProvider.js.

const AuthProvider = ({ children }) => {  xx 

return (
<AuthContext.Provider
  value = {{
    createUser,
    user,
    loginUser,
    logOut,
    loading,
    apartmentFromUser,
    roleFromUser,
    nameFromUser,
  }}
>
  {children}
</AuthContext.Provider>

export default AuthProvider;

Другие вопросы по теме