I am very new to React JS and Firebase. I tried to https://medium.com/ topic
"Building a Firebase Authentication and Private Route System in a React App"
After modifying the code and trial and error. I’m stuck in AuthProvider.js.
Everytime, I tried to submit a form from SignIn or LogIn Page.. i got an error saying
createUser is not a function
TypeError: createUser is not a function
at handleFormSubmit (http://localhost:3000/main.a5a57c81bfd5076aaa7d.hot-update.js:62:5)
at HTMLUnknownElement.callCallback (http://localhost:3000/static/js/bundle.js:29437:18)
This createUser
is passed on via Context in React.
AuthProvider.js
import {
createUserWithEmailAndPassword,
onAuthStateChanged,
signInWithEmailAndPassword,
signOut,
} from "firebase/auth";
import { createContext, useEffect, useState } from "react";
import PropTypes from "prop-types";
import auth from "./firebaseConfig";
export const AuthContext = createContext("");
const AuthProvider = ({ children }) => {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
const createUser = (email, password) => {
setLoading(true);
return createUserWithEmailAndPassword(auth, email, password);
};
const loginUser = (email, password) => {
setLoading(true);
return signInWithEmailAndPassword(auth, email, password);
};
const logOut = () => {
setLoading(true);
return signOut(auth);
};
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (currentUser) => {
setUser(currentUser);
setLoading(false);
});
return () => {
unsubscribe();
};
}, []);
const authValue = {
createUser,
user,
loginUser,
logOut,
loading,
};
return (
<AuthContext.Provider value={{ authValue }}>
{children}
</AuthContext.Provider>
);
};
AuthProvider.propTypes = {
children: PropTypes.node.isRequired,
};
export default AuthProvider;
SignUp.js
import { useContext, useState } from "react";
import { AuthContext } from "./AuthProvider";
import { updateProfile } from "firebase/auth";
import { useNavigate } from "react-router-dom";
const SignUp = () => {
const { createUser, user, loading } = useContext(AuthContext);
const [selectedImage, setSelectedImage] = useState(null);
const navigate = useNavigate();
// If authentication is still loading, display a loading indicator
if (loading) {
return (
<span className="loading loading-dots loading-lg flex item-center mx-auto"></span>
);
}
// If the user is already authenticated, redirect to the home page
if (user) {
navigate("/");
}
// Handle form submission for user registration
const handleFormSubmit = (e) => {
e.preventDefault();
const email = e.target.email.value;
const password = e.target.password.value;
createUser(email, password)
.then((result) => {
// Update user profile with display name
updateProfile(result.user, {
//displayName: name,
});
navigate("/");
console.log(result);
})
.catch((error) => {
console.log(error);
});
e.target.reset();
};
// Handle image upload (not shown in the code, but you can add it)
// Render the sign-up form
return (
<div>
<div className="min-h-screen bg-base-200">
<div className="hero-content flex-col">
<div className="card flex-shrink-0 w-full max-w-sm shadow-2xl bg-base-100">
<div className="card-body">
<form onSubmit={handleFormSubmit}>
<div className="form-control">
<label className="label">
<span className="label-text">Name</span>
</label>
<input
type="text"
name="name"
placeholder="Name"
className="input input-bordered"
/>
</div>
<div className="form-control">
<label className="label">
<span className="label-text">Email</span>
</label>
<input
type="email"
name="email"
placeholder="Email"
className="input input-bordered"
/>
</div>
<div className="form-control">
<label className="label">
<span className="label-text">Password</span>
</label>
<input
type="password"
name="password"
placeholder="Password"
className="input input-bordered"
/>
</div>
<div className="form-control mt-6">
<button className="btn btn-primary">Sign Up</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
);
};
export default SignUp;
I tried to make the Firebase Auth works by SignIn, SignUp page. This link to my AuthProvider page.
I hope the information of Signed In User could go through all components and page via Context, React
2
Answers
Since you are destructuring
createUser
from theAuthContext
you should not use curly brackets in theAuthContext.Provider
because it would bevalue.createUser
. See the code below :<AuthContext.Provider value={authValue}>
For more information, you can look at the docs.
Issue
The code is providing a context value that is an object with only an
authValue
property.Which means the
AuthContext
value is{ authValue }
and so if you wish to access thecreateUser
function the code would useauthValue.createUser
.The consuming code, however, is accessing anything but
authValue
from theAuthContext
, so these are all undefined properties.createUser
,user
, andloading
are all undefined.Solution
Ensure the consumers access correctly what is actually provided.
If the context values are passed in an
authValue
property:If the context values are passed directly:
Be sure to also specify a
AuthContext
default value that matches the usage/API.Example: