Firebase sendPasswordResetEmail not working in React - javascript

I have tried to create password reset option to web app with firebase and Other firebase options are works fine like GoogleLogin and Email Sign Up, but when i try sendPasswordResetEmail it returns following error,
TypeError: firebase__WEBPACK_IMPORTED_MODULE_1_.auth.sendPasswordResetEmail is not a function
Here's the Code,
firebase.js
import { initializeApp } from "firebase/app";
import { getAuth, GoogleAuthProvider, signInWithPopup } from "firebase/auth";
const firebaseConfig = {
apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
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
};
const app = initializeApp(firebaseConfig);
export const auth = getAuth(app);
export const provider = new GoogleAuthProvider();
export const signInWithGooglePopUp = signInWithPopup
export default app;
AuthContext.js
import React, { useContext, useState, useEffect } from "react"
import { auth, provider, signInWithGooglePopUp } 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)
}
function logout() {
return auth.signOut()
}
function resetPassword(email) {
alert('')
return auth.sendPasswordResetEmail(email).then((a) => {
alert(a)
})
}
function updateEmail(email) {
return currentUser.updateEmail(email)
}
function updatePassword(password) {
return currentUser.updatePassword(password)
}
function signupWithGoogle() {
return signInWithGooglePopUp(auth, provider).then((result) => {
console.log(result)
}).catch((error) => {
console.log(error)
})
}
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged(user => {
setCurrentUser(user)
setLoading(false)
})
return unsubscribe
}, [])
const value = {
currentUser,
login,
signup,
logout,
resetPassword,
updateEmail,
updatePassword,
signupWithGoogle
}
return (
<AuthContext.Provider value={value}>
{!loading && children}
</AuthContext.Provider>
)
}
ForgotPassword.js
import React, { useRef, useState } from "react"
import { Form, Button, Card, Alert } from "react-bootstrap"
import { useAuth } from "../contexts/AuthContext"
import { Link } from "react-router-dom"
export default function ForgotPassword() {
const emailRef = useRef()
const { resetPassword } = useAuth()
const [error, setError] = useState("")
const [message, setMessage] = useState("")
const [loading, setLoading] = useState(false)
async function handleSubmit(e) {
e.preventDefault()
try {
setMessage("")
setError("")
setLoading(true)
console.log('wait')
await resetPassword(emailRef.current.value)
console.log('done')
setMessage("Check your inbox for further instructions")
} catch (error) {
console.log(error)
setError("Failed to reset password")
}
setLoading(false)
}
return (
<>
<Card>
<Card.Body>
<h2 className="text-center mb-4">Password Reset</h2>
{error && <Alert variant="danger">{error}</Alert>}
{message && <Alert variant="success">{message}</Alert>}
<Form onSubmit={handleSubmit}>
<Form.Group id="email">
<Form.Label>Email</Form.Label>
<Form.Control type="email" ref={emailRef} required />
</Form.Group>
<Button disabled={loading} className="w-100" type="submit">
Reset Password
</Button>
</Form>
<div className="w-100 text-center mt-3">
<Link to="/login">Login</Link>
</div>
</Card.Body>
</Card>
<div className="w-100 text-center mt-2">
Need an account? <Link to="/signup">Sign Up</Link>
</div>
</>
)
}
What's wrong here, Thanks in Advance.

You are using Firebase Modular SDK (V9.0.0+) where sendPasswordResetEmail is a function and not a method on Auth instance. So that should be:
import { sendPasswordResetEmail } from "firebase/auth"
import { auth } from "../firebase"
function resetPassword(email) {
return sendPasswordResetEmail(auth, email).then((a) => {
alert("Password reset email sent")
})
}
The same applies for others functions like createUserWithEmailAndPassword(), signOut(), etc. I'm not sure why the error shows up for this one only.
Do checkout the documentation of Firebase Auth to learn more about these functions.

Related

useNavigate redirecting but not loading

the URL shows that it is login page but everything is white, and when I reload it loads the page.
in the console says that many variables from the previous page are null, it seems like it's still on the previous page. why is this happening?
The previous page and the code:
import React, { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import '../styles/UserProfile.css'
import { useAuth } from '../services/authContext'
export default function UserProfile() {
const { currentUser, logout } = useAuth()
const navigate = useNavigate()
const [errorMessage, setErrorMessage] = useState(null)
async function handleLogout() {
try {
await logout()
navigate("/login")
} catch (error) {
console.log(error)
setErrorMessage('An error ocurred when trying to logout')
}
}
return (
<div className="container profile">
<div className="profile">
<h1>Profile</h1>
{errorMessage && (
<div className="error-container">
<strong>{errorMessage}</strong>
</div>
)}
<div className="row">
<h3>Email</h3>
<p>{currentUser.email}</p>
</div>
<div className="row">
<a>Change email</a>
</div>
<div className="row">
<a>Reset password</a>
</div>
<button onClick={handleLogout}>Logout</button>
</div>
</div>
)
}
and when i click logout this happens:
when i reload it loads normally
useAuth code:
import React, { createContext, useContext, useEffect, useState } from 'react'
import {
createUserWithEmailAndPassword,
onAuthStateChanged,
signInWithEmailAndPassword,
signOut,
} from 'firebase/auth'
import { auth } from '../firebase'
const AuthContext = createContext()
export function useAuth() {
return useContext(AuthContext)
}
export function AuthProvider({ children }) {
const [currentUser, setCurrentUser] = useState()
function signUp(email, password) {
return createUserWithEmailAndPassword(auth, email, password)
}
function login(email, password) {
return signInWithEmailAndPassword(auth, email, password)
}
function logout() {
return signOut(auth)
}
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, user => {
setCurrentUser(user)
})
return unsubscribe
}, [])
return (
<AuthContext.Provider
value={{
signUp: signUp,
login: login,
logout: logout,
currentUser: currentUser,
}}
>
{children}
</AuthContext.Provider>
)
}
login code:
import React, { useState } from 'react'
import { useAuth } from '../services/authContext'
import { useNavigate, Link } from 'react-router-dom'
import Header from '../components/Header'
export default function Login() {
const { login } = useAuth()
const navigate = useNavigate()
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [loading, setLoading] = useState(false)
const [errorMessage, setErrorMessage] = useState(null)
async function handleSubmit(element) {
element.preventDefault()
setLoading(true)
if (password.length < 6) {
setErrorMessage('The password need to have at least 6 characters!')
setLoading(false)
return
}
try {
await login(email, password)
navigate('/')
} catch (error) {
setErrorMessage('An error occured when trying to login')
}
setLoading(false)
}
return (
<div className="container">
<Header />
<h2>Login</h2>
{errorMessage && (
<div className="error-container">
<strong>{errorMessage}</strong>
</div>
)}
<form onSubmit={handleSubmit}>
<label>Email</label>
<input
type="email"
value={email}
onChange={e => setEmail(e.target.value)}
/>
<label>Password</label>
<input
type="password"
value={password}
onChange={e => {
setPassword(e.target.value)
}}
/>
<button disabled={loading} className="button-block" type="submit1">
Login
</button>
</form>
<div className="center">
<p>
ForgotPassword ? <Link to="/forgot-password">Reset password</Link>
</p>
<p>
Don't have an account ? <Link to="/signup">Create account</Link>
</p>
</div>
</div>
)
}
i consoled log currentUser and currentUser.email before logout, and it's not null, this happens after logging out.
UserProfile.jsx:32:1 is <p>{currentUser.email}</p>. As far as I can tell it appears the currentUser object is nullified and the UserProfile component is rerendered at least once prior to the navigation action being effected to navigate the user to the "/login" path. The UserProfile component falls over when attempting to access currentUser.email when currentUser is null.
You should place a guard on the UI to only render valid content when currentUser is non-null.
Example:
export default function UserProfile() {
const { currentUser, logout } = useAuth();
const navigate = useNavigate();
const [errorMessage, setErrorMessage] = useState(null);
async function handleLogout() {
try {
await logout();
navigate("/login");
} catch (error) {
console.log(error);
setErrorMessage('An error ocurred when trying to logout');
}
}
if (!currentUser) {
return <div>No Current user. Log in.</div>;
}
return (
<div className="container profile">
<div className="profile">
<h1>Profile</h1>
{errorMessage && (
<div className="error-container">
<strong>{errorMessage}</strong>
</div>
)}
<div className="row">
<h3>Email</h3>
<p>{currentUser.email}</p>
</div>
<div className="row">
<a>Change email</a>
</div>
<div className="row">
<a>Reset password</a>
</div>
<button onClick={handleLogout}>Logout</button>
</div>
</div>
)
}

React/Firebase error "Uncaught (in promise) TypeError: (0 , _firebase__WEBPACK_IMPORTED_MODULE_1__.default) is not a function"

Trying to implement user authentication using firebase into my react app. I have a firebase.js file where the register/login/logout functions are defined and then imported into the login/register screens. I don't have any errors until I actually try to register a user, then I get the error in the title.
import { useState } from 'react';
import { Link } from "react-router-dom";
import register from "../firebase";
import "../css/RegisterScreen.css";
function RegisterScreen() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
const handleSubmit = async (e) => {
e.preventDefault();
if (password == '') {
setError("Empty Password");
} else {
setEmail("");
setPassword("");
const res = await register(email, password);
if (res.error) setError(res.error)
}
};
return (
<div className="register">
<h2>Sign Up</h2>
<div className="registerContainer">
{error ? <div>{error}</div>: null}
<form onSubmit={handleSubmit}>
<input
type="email"
className="registerBox"
value={email}
placeholder="Email Address"
onChange={(event) => {
setEmail(event.target.value);
}}
/>
<input
type="password"
className="registerBox"
value={password}
placeholder="Password"
onChange={(event) => {
setPassword(event.target.value);
}}
/>
<button
className="registerButton"
type="submit">
Register
</button>
</form>
<div>
Already registered? <Link to="/login">Login</Link>
</div>
</div>
</div>
)
}
export default RegisterScreen
This line of code in particular is where the error occurs
const res = await register(email, password);
Here is the firebase.js file and the register function created there
import { initializeApp } from "firebase/app";
import {
getAuth,
createUserWithEmailAndPassword,
signInWithEmailAndPassword,
signOut,
} from "firebase/auth";
import {
getFirestore,
addDoc,
collection
} from "firebase/firestore";
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const db = getFirestore(app);
const register = async (email, password) => {
try {
const userCredential = await createUserWithEmailAndPassword(auth, email, password);
const user = userCredential.user;
await addDoc(collection(db, "users"), {
uid: user.uid,
email: user.email,
});
return true
} catch (error) {
return {error: error.message}
}
};
const login = async (email, password) => {
try {
const userCredential = await signInWithEmailAndPassword(auth, email, password);
const user = userCredential.user;
return true
} catch (error) {
return {error: error.message}
}
};
const logOut = async() => {
try {
await signOut(auth)
return true
} catch (error) {
return false
}
};
export default {
register,
login,
logOut,
db,
auth,
}
You are not exporting any function from firebase.js but trying to import register function. Instead try exporting the Firebase services and defining the function in the register screen or export the function itself. Try:
// firebase.js
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const db = getFirestore(app);
export { auth, db } // no default
import { auth } from "../firebase";
const handleSubmit = async (e) => {
e.preventDefault();
if (password == '') {
setError("Empty Password");
} else {
setEmail("");
setPassword("");
try {
const userCredential = await createUserWithEmailAndPassword(auth, email, password);
const user = userCredential.user;
await addDoc(collection(db, "users"), {
uid: user.uid,
email: user.email,
});
console.log("User created", user)
} catch (error) {
console.log(error.message)
}
}
};

react doesn't update the data, only after reloading page

It is my Auth Login form. I have AuthContext. Let's try log in.
I've clicked "log in" button. And we see AuthContext "user" : underfind
Then click reload page, and here we go, we have logged in
Why does it work like that?
Login.js
import React, {useState} from 'react'
import {useLogin} from '../hooks/useLogin'
import { useNavigate } from 'react-router-dom'
const Login = () => {
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const {login, error, isLoading} = useLogin()
let navigate = useNavigate()
const handleSubmit = async (e) => {
e.preventDefault()
await login(email, password)
}
return(
<div className='container'>
<h1>
login page
</h1>
<form className={'d-flex flex-column'} onSubmit={handleSubmit}>
<h3>Log in</h3>
<label>Email:</label>
<input
type={'email'}
onChange={(e) => setEmail(e.target.value)}
/>
<label>Password</label>
<input
type={'password'}
onChange={(e) => setPassword(e.target.value)}
/>
<button disabled={isLoading} type={'submit'}>
Log in
</button>
{error && <div className={'error'}>
{error}
</div>}
</form>
</div>
)
}
export default Login;
useLogin.js
import { useState } from "react";
import { useAuthContext } from "./useAuthContext";
export const useLogin = () => {
const [error, setError] = useState(null)
const [isLoading, setIsLoading] = useState(null)
const {dispatch} = useAuthContext()
const login = async (email, password) => {
setIsLoading(true)
setError(null)
const response = await fetch('/api/user/login', {
method:'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({email, password})
})
const json = await response.json()
if(!response.ok){
setIsLoading(false)
setError(json.error)
}
if(response.ok){
localStorage.setItem('user', JSON.stringify(json))
dispatch({type:'LOGIN', paylaod:json})
setIsLoading(false)
}
}
return {login, isLoading, error}
}
AuthContext.js
import { createContext, useReducer, useEffect } from "react";
export const AuthContext = createContext()
export const authReducer = (state, action) => {
switch(action.type){
case 'LOGIN':
return {user: action.payload}
case 'LOGOUT':
return {user:null}
default:
return state
}
}
export const AuthContextProvider = ({children}) => {
const [state, dispatch] = useReducer(authReducer, {
user:null
})
useEffect(() => {
const user = JSON.parse(localStorage.getItem('user'))
if(user){
dispatch({type:'LOGIN', payload: user})
}
}, [])
console.log('AuthContext state', state)
return(
<AuthContext.Provider value={{...state, dispatch}}>
{children}
</AuthContext.Provider>
)
}
useAuthContext.js
import { AuthContext } from "../context/AuthContext";
import { useContext } from "react";
export const useAuthContext = () => {
const context = useContext(AuthContext)
if(!context){
throw Error('useAuthContext must be used inside an AuthContextProvider')
}
return context
}
here is Navbar.js
import React from "react";
import { useAuthContext } from "../hooks/useAuthContext";
import { useLogout } from "../hooks/useLogout";
import { Link } from "react-router-dom";
const Nav = () => {
const {logout} = useLogout()
const {user} = useAuthContext()
const handleClick= () => {
logout()
}
return(
<div>
{user && (
<div className="bg-dark text-light align-item-center d-flex justify-content-between m-auto container-fluid p-2">
<span className="m-0 p-0 d-flex align-item-center">{user.email}</span>
<button className="btn btn-outline-danger" onClick={handleClick}>logout</button>
</div>
)}
{!user && (
<div className="d-flex justify-content-between">
<Link to='/'>
<button>HOME</button>
</Link>
<Link to='/login'>
<button>LOGIN</button>
</Link>
<Link to='/signup'>
<button>SIGNUP</button>
</Link>
</div>
)}
</div>
)
}
export default Nav
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { AuthContextProvider } from './context/AuthContext';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<AuthContextProvider>
<App />
</AuthContextProvider>
</React.StrictMode>
);
app.js
import {BrowserRouter, Routes, Route} from 'react-router-dom'
import Nav from './components/Nav';
import Home from './pages/home';
import Login from './pages/login';
import Signup from './pages/signup';
function App() {
return (
<div>
<BrowserRouter>
<Nav/>
<Routes>
<Route path={'/'} element={<Home/>}/>
<Route path={'/login'} element={<Login/>}/>
<Route path={'/signup'} element={<Signup/>}/>
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
I don't think it is server error.
There's a spelling mistake in useLogin payload is written wrong
dispatch({type:'LOGIN', paylaod:json});
// Should be: Payload
dispatch({type:'LOGIN', payload:json});
The root cause seems to be a typo:
dispatch({type:'LOGIN', paylaod:json})
has a typo in paylaod, so the reducer's
case 'LOGIN':
return {user: action.payload}
basically just sets {user: undefined}.
You should add error checking to your reducer, or better yet switch to a typed language like TypeScript so typos like these are caught at type-check time.
Since the user is not in the component state, it will not re-render after it is set (which seems to happen after first rendering). Add a useEffect with dependency on the value that updates the state and it should be good. F.ex:
const Nav = () => {
const {contextUser} = useAuthContext()
const [user, setUser] = useState()
...
useEffect(() => {
if (contextUser) {
setUser(contextUser)
}
}, [contextUser])
...
}

Problem with JS functions, using Firebase and React

thanks for your patience. I'm implementing Firebase on my site but when I call the signup function in FormUp.js (declared in AuthContext.js) it doesn't refer to the function definition. This causes the function called in FormUp.js, not to call its own function defined in AuthContext.js, but falls into the catch branch ('Failed to create an account'). I don't understand why. Hope someone can help me, thanks!
Error:
TypeError: _firebase__WEBPACK_IMPORTED_MODULE_1__.auth.createUserWithEmailAndPassword is not a function
at signup (bundle.js:4226:56)
at handleSubmit (bundle.js:2575:13)
at HTMLUnknownElement.callCallback (bundle.js:41062:18)
at Object.invokeGuardedCallbackDev (bundle.js:41111:20)
at invokeGuardedCallback (bundle.js:41171:35)
at invokeGuardedCallbackAndCatchFirstError (bundle.js:41186:29)
at executeDispatch (bundle.js:45421:7)
at processDispatchQueueItemsInOrder (bundle.js:45453:11)
at processDispatchQueue (bundle.js:45466:9)
at dispatchEventsForPlugins (bundle.js:45477:7)
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 a useEffect cleanup function.
at Navbar (http://localhost:3000/static/js/bundle.js:3361:76)
at Home
Code:
AuthContext.js
import React, { useContext, useState, useEffect } from "react";
import { auth } from "../firebase";
import { createUserWithEmailAndPassword } from "firebase/auth";
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);
}
function logout() {
return auth.signOut();
}
function resetPassword(email) {
return auth.sendPasswordResetEmail(email);
}
function updateEmail(email) {
return currentUser.updateEmail(email);
}
function updatePassword(password) {
return currentUser.updatePassword(password);
}
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged((user) => {
setCurrentUser(user);
setLoading(false);
});
return unsubscribe;
}, []);
const value = {
currentUser,
login,
signup,
logout,
resetPassword,
updateEmail,
updatePassword,
};
return (
<AuthContext.Provider value={value}>
{!loading && children}
</AuthContext.Provider>
);
}
firebase.js
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
const firebaseConfig = {
//Hidden
};
const app = initializeApp(firebaseConfig);
const auth = getAuth();
export { app, auth };
FormUp.js
import React, { useRef, useState } from "react";
import { Link } from "react-router-dom";
import {
FormUser,
Input,
Label,
Subtitle,
TextWrapper,
TopLine,
FormButton,
Credentials,
HomePage,
SignInLink,
SignInText,
RedirectSignIn,
Credential,
} from "./Form.elements";
import { FaAngleLeft } from "react-icons/fa";
import { useAuth } from "../../contexts/AuthContext";
import { Alert } from "bootstrap";
const FormUp = ({
primary,
lightBg,
lightTopLine,
lightTextDesc,
buttonLabel,
description,
topLine,
}) => {
const emailRef = useRef();
const passwordRef = useRef();
const passwordConfirmRef = useRef();
const { signup } = useAuth();
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
async function handleSubmit(e) {
e.preventDefault();
if (passwordRef.current.value !== passwordConfirmRef.current.value) {
return setError("Password do not match");
}
try {
setError("");
setLoading(true);
await signup(emailRef.current.value, passwordRef.current.value);
} catch {
setError("Failed to create an account");
}
setLoading(false);
}
return (
<>
<style>
#import
url('https://fonts.googleapis.com/css2?family=Poppins:wght#100;200;300;400;500;600;700;800;900&display=swap');
</style>
<FormUser lightBg={lightBg} onSubmit={handleSubmit}>
<TextWrapper>
<HomePage href="/">
<FaAngleLeft />
<TopLine lightTopLine={lightTopLine}>{topLine}</TopLine>
</HomePage>
<Subtitle lightTextDesc={lightTextDesc}>{description}</Subtitle>
{error && (
<h5 style={{ color: "red", paddingBottom: "30px" }}>{error}</h5>
)}
<Credentials>
<Credential id="email">
<Label>Email</Label>
<Input
ref={emailRef}
required
type="email"
placeholder="Email..."
></Input>
</Credential>
<Credential id="password">
<Label>Password</Label>
<Input
ref={passwordRef}
required
type="password"
placeholder="Password..."
></Input>
</Credential>
<Credential id="password-confirm">
<Label>Password confirmation</Label>
<Input
ref={passwordConfirmRef}
required
type="password"
placeholder="Password confirmation..."
></Input>
</Credential>
</Credentials>
<FormButton disabled={loading} type="submit" big primary={primary}>
{buttonLabel}
</FormButton>
<RedirectSignIn>
<SignInText>Already have an account?</SignInText>
<SignInLink href="/sign-in">Log in</SignInLink>
</RedirectSignIn>
</TextWrapper>
</FormUser>
</>
);
};
export default FormUp;

JS functions error using Firebase and React

Thanks for your patience. I'm implementing Firebase on my site but when I call the signup function in FormUp.js (declared in AuthContext.js) it doesn't refer to the function definition. This causes the function called in FormUp.js, not to call its own function defined in AuthContext.js, but falls into the catch branch ('Failed to create an account'). I don't understand why. Hope someone can help me, thanks!
Error:
TypeError: _firebase__WEBPACK_IMPORTED_MODULE_1__.auth.createUserWithEmailAndPassword is not a function
at signup (bundle.js:4226:56)
at handleSubmit (bundle.js:2575:13)
at HTMLUnknownElement.callCallback (bundle.js:41062:18)
at Object.invokeGuardedCallbackDev (bundle.js:41111:20)
at invokeGuardedCallback (bundle.js:41171:35)
at invokeGuardedCallbackAndCatchFirstError (bundle.js:41186:29)
at executeDispatch (bundle.js:45421:7)
at processDispatchQueueItemsInOrder (bundle.js:45453:11)
at processDispatchQueue (bundle.js:45466:9)
at dispatchEventsForPlugins (bundle.js:45477:7)
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 a useEffect cleanup function.
at Navbar (http://localhost:3000/static/js/bundle.js:3361:76)
at Home
Code:
AuthContext.js
import React, { useContext, useState, useEffect } from "react";
import { auth } from "../firebase";
import { createUserWithEmailAndPassword } from "firebase/auth";
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);
}
function logout() {
return auth.signOut();
}
function resetPassword(email) {
return auth.sendPasswordResetEmail(email);
}
function updateEmail(email) {
return currentUser.updateEmail(email);
}
function updatePassword(password) {
return currentUser.updatePassword(password);
}
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged((user) => {
setCurrentUser(user);
setLoading(false);
});
return unsubscribe;
}, []);
const value = {
currentUser,
login,
signup,
logout,
resetPassword,
updateEmail,
updatePassword,
};
return (
<AuthContext.Provider value={value}>
{!loading && children}
</AuthContext.Provider>
);
}
firebase.js
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
const firebaseConfig = {
//Hidden
};
const app = initializeApp(firebaseConfig);
const auth = getAuth();
export { app, auth };
FormUp.js
import React, { useRef, useState } from "react";
import { Link } from "react-router-dom";
import {
FormUser,
Input,
Label,
Subtitle,
TextWrapper,
TopLine,
FormButton,
Credentials,
HomePage,
SignInLink,
SignInText,
RedirectSignIn,
Credential,
} from "./Form.elements";
import { FaAngleLeft } from "react-icons/fa";
import { useAuth } from "../../contexts/AuthContext";
import { Alert } from "bootstrap";
const FormUp = ({
primary,
lightBg,
lightTopLine,
lightTextDesc,
buttonLabel,
description,
topLine,
}) => {
const emailRef = useRef();
const passwordRef = useRef();
const passwordConfirmRef = useRef();
const { signup } = useAuth();
const [error, setError] = useState("");
const [loading, setLoading] = useState(false);
async function handleSubmit(e) {
e.preventDefault();
if (passwordRef.current.value !== passwordConfirmRef.current.value) {
return setError("Password do not match");
}
try {
setError("");
setLoading(true);
await signup(emailRef.current.value, passwordRef.current.value);
} catch {
setError("Failed to create an account");
}
setLoading(false);
}
return (
<>
<style>
#import
url('https://fonts.googleapis.com/css2?family=Poppins:wght#100;200;300;400;500;600;700;800;900&display=swap');
</style>
<FormUser lightBg={lightBg} onSubmit={handleSubmit}>
<TextWrapper>
<HomePage href="/">
<FaAngleLeft />
<TopLine lightTopLine={lightTopLine}>{topLine}</TopLine>
</HomePage>
<Subtitle lightTextDesc={lightTextDesc}>{description}</Subtitle>
{error && (
<h5 style={{ color: "red", paddingBottom: "30px" }}>{error}</h5>
)}
<Credentials>
<Credential id="email">
<Label>Email</Label>
<Input
ref={emailRef}
required
type="email"
placeholder="Email..."
></Input>
</Credential>
<Credential id="password">
<Label>Password</Label>
<Input
ref={passwordRef}
required
type="password"
placeholder="Password..."
></Input>
</Credential>
<Credential id="password-confirm">
<Label>Password confirmation</Label>
<Input
ref={passwordConfirmRef}
required
type="password"
placeholder="Password confirmation..."
></Input>
</Credential>
</Credentials>
<FormButton disabled={loading} type="submit" big primary={primary}>
{buttonLabel}
</FormButton>
<RedirectSignIn>
<SignInText>Already have an account?</SignInText>
<SignInLink href="/sign-in">Log in</SignInLink>
</RedirectSignIn>
</TextWrapper>
</FormUser>
</>
);
};
export default FormUp;
Well, the problem here is, as the error message suggest, that auth does not have a property called createUserWithEmailAndPassword. What you are searching for is not part of auth. Your code should be something like
function signup(email, password) {
return createUserWithEmailAndPassword(auth, email, password);
}
instead of
function signup(email, password) {
return auth.createUserWithEmailAndPassword(email, password);
}
Check this (if you are using version 8 of the SDK, then you need to use a different approach)
https://firebase.google.com/docs/auth/web/password-auth#create_a_password-based_account
My suggestion is to add a linter to your project to easily catch these issues. In this case the issue would have been immediately visible since the import of createUserWithEmailAndPassword is not used.

Categories