base.jsx:
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
const firebaseConfig = {
config
};
export const app = initializeApp(firebaseConfig);
export const auth = getAuth();
Register.jsx
import React, { useState } from "react";
import { auth } from "../components/base";
import { Link, useNavigate } from "react-router-dom";
function Register() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState(null);
let navigate = useNavigate();
const handleRegister = async (e) => {
e.preventDefault();
try {
await auth.createUserWithEmailAndPassword(email, password);
await auth.signInWithEmailAndPassword(email, password);
navigate("/");
} catch (error) {
setError(error.message);
}
};
return (
<div className="register">
<div className="container">
<div className="box">
<form onSubmit={handleRegister}>
<h2>Register</h2>
<div className="form-group">
<label htmlFor="email">Email</label>
<input
type="email"
className="form-control"
id="email"
placeholder="Enter email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div className="form-group">
<label htmlFor="password">Password</label>
<input
type="password"
className="form-control"
id="password"
placeholder="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<button type="submit" className="btn btn-primary">
Register
</button>
<div>{error && <p className="error">{error}</p>}</div>
</form>
<p className="sign-up">
Already have an account?
<Link to="/login">
<span>Login</span>
</Link>
</p>
</div>
</div>
</div>
);
}
export default Register;
enter image description here
It's pretty much self explanatory, can you guys please help me fix this issue? I've been struggling for 2 hours.
I want createUserWithEmailAndPassword to work in Register.jsx so I can later on sign in Login.jsx with the same information. However on the website when I click the submit button in Register.jsx, auth.createUserWithEmailAndPassword is not a function pops out
You're using the v9 SDK version, which uses a modular API with top-level functions. So createUserWithEmailAndPassword is not longer a method on the auth object, but is now a top-level function that you have to import similar to what you do for getAuth and to which you then pass the auth object as its first parameter:
createUserWithEmailAndPassword(auth, "username", "password")
When you are programming this new API or getting errors otherwise, I recommend keeping the documentation handy. In this case you can see code similar to what you're trying and what I have above in the documentation on creating a user. Also have a look at the blog post introducing the modular SDK, and the upgrade guide.
Related
I'm trying to fetch the uid and token through the URL pathname using match in my React app. But I got error:
Uncaught TypeError: n is undefined
and this is my code snippet:
const ResetPasswordConfirm = ( {match, reset_password_confirm} ) => {
...
const onSubmit = e=> {
e.preventDefault();
const uid = match.params.uid;
const token = match.params.token;
reset_password_confirm(uid, token, new_password, re_new_password);
setRequestSent(true);
};
};
According to this thread: https://stackoverflow.com/questions/70609785/uncaught-typeerror-match-is-undefined#:~:text=react%2Drouter%2Ddom%20v5,render%20or%20children%20prop%20functions.
It says it might have something to do with the version of react router, so I tried to use useParams(), but I found it hard to implement it...
I also tried to use matchPath, but I can find few examples.
Can anybody help me with this issue please?
Update:
react-router-dom version: 6.8.0
ResetPasswordConfirm is running in my container package.
import React, { useState } from "react";
import { Navigate, useParams } from 'react-router-dom';
import { connect } from 'react-redux';
import { reset_password_confirm } from '../actions/auth';
const ResetPasswordConfirm = ( {match, reset_password_confirm} ) => {
const [requestSent, setRequestSent] = useState(false);
const [formData, setFormData] = useState({
new_password: '',
re_new_password: ''
});
const { new_password, re_new_password } = formData;
const onChange = e => setFormData({ ...formData, [e.target.name]: e.target.value });
const onSubmit = e=> {
e.preventDefault();
const uid = match.params.uid;
const token = match.params.token;
reset_password_confirm(uid, token, new_password, re_new_password);
setRequestSent(true);
};
// Is the user sending the request?
// Redirect them to the home page
if (requestSent) {
return <Navigate to='/'/>
}
return (
<div className="container mt-5">
<form onSubmit={e => onSubmit(e)}>
{/* <div className="form-group">
<input className="form-control" type="email" placeholder="Email" name="email" value={email} onChange={e => onChange(e)} required></input>
</div>
<div className="form-group">
<input className="form-control" type="password" placeholder="Password" name="password" value={password} onChange={e => onChange(e)} minLength='6' required></input>
</div>
<button className="btn btn-primary" type="submit">Login</button> */}
<div className="form-group">
<label htmlFor="exampleInputPassword1">Password</label>
<input
type="password"
className="form-control"
id="exampleInputPassword1"
placeholder="New Password"
name="new_password"
value={new_password}
onChange={e => onChange(e)}
minLength='6'
required></input>
</div>
<div className="form-group">
<label htmlFor="exampleInputPassword1">Password</label>
<input
type="password"
className="form-control"
id="exampleInputPassword1"
placeholder="Confirm New Password"
name="re_new_password"
value={re_new_password}
onChange={e => onChange(e)}
minLength='6'
required></input>
</div>
<button type="submit" className="btn btn-primary">Reset Password</button>
</form>
</div>
);
};
export default connect(null, { reset_password_confirm }) (ResetPasswordConfirm);
Sorry for the lo-fi question. I will try to do better.
I tried to use useParams to fetch my uid
const onSubmit = e => {
...
let{uid} = useParams()
}
There are no longer route props in react-router-dom routed components, i.e. there is not any injected match prop. You'll use the useParams hook to access the route path params in RRDv6. You can't use React hooks in nested callbacks, they must be called in the function body of a React component or in custom React hooks. Use the useParams hook in the component body and destructure the uid and token path params. Since you are using hooks you may as well also import and use the useNavigate hook and issue the navigation action at the end of the form's onSubmit handler instead of enqueueing a state update.
import React, { useState } from "react";
import { useParams, useNavigate } from 'react-router-dom';
import { useDispatch } from 'react-redux';
import { reset_password_confirm } from '../actions/auth';
const ResetPasswordConfirm = () => {
const dispatch = useDispatch();
const navigate = useNavigate();
const { uid, token } = useParams();
const [formData, setFormData] = useState({
new_password: '',
re_new_password: ''
});
const onChange = e => setFormData(formData => ({
...formData,
[e.target.name]: e.target.value
}));
const onSubmit = e => {
e.preventDefault();
const { new_password, re_new_password } = formData;
dispatch(reset_password_confirm(uid, token, new_password, re_new_password));
navigate("/");
};
return (
...
);
};
export default ResetPasswordConfirm;
I have two forms.
Login.jsx:
import React, {Fragment, useState } from "react";
import axios from "axios";
export const Login = (props) => {
const [user, setUser] = useState('');
const [pass, setPass] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
const data = {
KorisnickoIme: user,
Lozinka: pass
};
const url ='https://localhost:44357/api/Fin/Login';
axios.post(url, data).then((result)=>{
alert(result.data);
}).catch((error)=>{
alert(error);
})
};
return (
<Fragment>
<div className="auth-form-container">
<h2>Пријава</h2>
<form className="login-form" onSubmit={handleSubmit}>
<label htmlFor="user">Корисничко ме</label>
<input value ={user} onChange ={(e) => setUser(e.target.value)}placeholder="korisnicko_ime" id="user" name="user" required/>
<label htmlFor="email">Лозинка</label>
<input
value={pass}
onChange={(e) => setPass(e.target.value)}
type="password"
placeholder="********"
></input>
<button type="submit">Пријави се</button>
</form>
<button
className="link-btn"
onClick={() => props.onFormSwitch("register")}
>
Немаш налог? Региструј се овде.
</button>
</div>
</Fragment>
);
};
and Register.jxs:
import React, {Fragment, useState} from "react";
import axios from "axios";
import { ProfileSetUp } from './ProfileSetUp';
export const Register = (props) => {
const [email, setEmail] = useState('');
const [pass, setPass] = useState('');
const [name, setName] = useState('');
const [user, setUser] = useState('');
const [lastname, setLastname] = useState('');
const [checkPass, setCheckPass] = useState('');
const handleSubmit = (e) => {
if(pass==checkPass){
e.preventDefault();
const data = {
KorisnickoIme:user,
Ime: name,
Prezime: lastname,
Email: email,
Lozinka: pass
};
const url ='https://localhost:44357/api/Fin/Registration';
axios.post(url, data).then((result)=>{
alert(result.data);
}).catch((error)=>{
alert(error);
})
}else{
alert("Лозинке се не поклапају");
}
}
return(
<Fragment>
<div className="auth-form-container">
<h2>Регистрација</h2>
<form className="reg-form" onSubmit={handleSubmit}>
<label htmlFor="name">Име</label>
<input value ={name} onChange ={(e) => setName(e.target.value)}placeholder="Унесите Ваше име" id="name" name="name" required/>
<label htmlFor="lastname">Презиме</label>
<input value ={lastname} onChange ={(e) => setLastname(e.target.value)}placeholder="Унесите Ваше презиме" id="lastname" name="lastname" required/>
<label htmlFor="email">Е-маил</label>
<input value ={email} onChange ={(e) => setEmail(e.target.value)}type="email" placeholder="vasmail#fink.com" id="email" name="email" required/>
<label htmlFor="user">Корисничко ме</label>
<input value ={user} onChange ={(e) => setUser(e.target.value)}placeholder="Унесите Ваше korisnicko_ime" id="user" name="user" required/>
<label htmlFor="password">Лозинка</label>
<input value ={pass} onChange ={(e) => setPass(e.target.value)}type="password" placeholder="********" id="password" name="password" required/>
<label htmlFor="checkPass">Потврдите лозинку</label>
<input value ={checkPass} onChange ={(e) => setCheckPass(e.target.value)}type="password" placeholder="********" id="checkPass" name="checkPass" required/>
<button type="submit">Региструј се</button>
</form>
<button className="link-btn" onClick={() => props.onFormSwitch('login')}>Имате налог? Пријавите се.</button>
</div>
</Fragment>
)
}
/* */
After registering I want to send user to Login form but I am not sure how should I do it. Here is App.js just in case:
import React, {useState} from 'react';
import './App.css';
import { Register } from './Register';
import { Login } from './Login';
import { ProfileSetUp } from './ProfileSetUp';
function App() {
const [currentForm, setCurrentForm] = useState('login');
const toggleForm = (formName) => {
setCurrentForm(formName);
}
return (
<div className="App">
{
currentForm === "login" ? <Login onFormSwitch={toggleForm} /> : <Register onFormSwitch={toggleForm} />
}
</div>
);
}
export default App;
I am not sure how React page is represented so I am not sure how to use window.open() etc.
I followed one tutorial where is shown how to make this toggle switch function, which I like but I think that will make me troubles with other pages.
You can use the react-router package to link between different pages and pass data. Here is the documentation for the package https://reactrouter.com/en/main.
If you don't want to navigate to different components using routing, you could just use state variables to show/hide components included in a single parent component.
Trying to POST request to send data to database but it always shows 400 bad request.
The AuthReducer file is as follow. Data is not getting posted when done in Frontend but its properly working when tested in postman api.
export const Register = (username, email , password) => async(disptach) => {
try{
disptach({type:REGISTER_USER_REQUEST})
const config = {
Headers:{
'Content-Type':'application/json'
}
}
const { data } = await axios.post('/EShop/register', {username ,email , password} , config)
disptach({
type:REGISTER_USER_SUCCESS,
payload:data.user
})
}catch(error){
disptach({
type:REGISTER_USER_FAIL,
payload : error.response.data.message
})
}
}
The register form is as follow..
import React, { useState, useEffect } from "react";
import { Link, useNavigate } from "react-router-dom"
import { useSelector, useDispatch } from "react-redux"
import Loader from "./loader";
import { Register } from "../actions/UserAction";
import "../css-files/Account.css"
export default function register() {
const [email, setemail] = useState('');
const [password, setpassword] = useState('');
const [username, setusername] = useState('');
const disptach = useDispatch();
const navigate = useNavigate();
const { isAuthenticated, error, loading } = useSelector(state => state.user)
useEffect(() => {
if (isAuthenticated) {
navigate('/account/login')
}
}, [disptach, isAuthenticated])
const SubmitRegisterHandler = (e) => {
e.preventDefault()
disptach(Register(username, email, password))
}
return (
<div id="Account_container">
{loading ?
<Loader />
:
<div id="wrapper">
<div id="Wrap_First">
<img src="https://res.cloudinary.com/dqxozrie1/image/upload/v1659935744/eshop/online-registration-sign-up_gfb2gs.webp" />
</div>
<div id="Wrap_Second">
<div id="login">
<h2>Create New Account</h2>
<form onSubmit={SubmitRegisterHandler}>
<input
required
type="text"
placeholder="Username"
value={username}
onChange={(e) => { setusername(e.target.value) }}
/>
<input
required
type="email"
placeholder="Email"
value={email}
onChange={(e) => { setemail(e.target.value) }}
/>
<input
required
type="password"
placeholder="Password"
value={password}
onChange={(e) => { setpassword(e.target.value) }}
/>
<button>Register</button>
</form>
<p id="existing_acc"><Link to="/account/login">Already have an account !</Link></p>
</div>
</div>
</div>
}
</div>
);
}
It gives 400 bad request always. Please help me how to resolve this issue.
i am using the useNavigate hook inside of react to direct users to a home page after successful login. everything i've read online suggests that i should use the useNavigate hook inside of a useEffect block, but when i do so, it triggers an infinite loop: Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
the odd thing is, though, that the warning only seems to occur after logging in for a second time. what i mean is that it will work on the first login after starting the server & client, but logging in a second, third, etc. time results in a Maximum update depth exceeded warning.
i use the useNavigate hook in two separate files, a login for users and a login for admin, both of which are below.
for further clarification on the issue arising only on the second login and beyond, it occurs regardless of whether i log in as admin or as a user. for instance, if my first login is as an admin, the Maximum update depth exceeded warning will occur regardless of whether my next login is as a user or as an admin. the same is true if my first login is as a user.
what i've tried so far:
removing navigate as from the dependency arrays (results in same warning)
removing the useEffect blocks (results in warnings to put the useNavigate hook inside of a useEffect hook. the login functionality breaks)
removing the dependency array altogether (results in the same warning)
the error when i login as user:
react-dom.development.js:86 Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
at Navigate (http://localhost:3000/static/js/bundle.js:42950:5)
at Routes (http://localhost:3000/static/js/bundle.js:43067:5)
at div
at Router (http://localhost:3000/static/js/bundle.js:43000:15)
at BrowserRouter (http://localhost:3000/static/js/bundle.js:41809:5)
at App
the error when i login as admin:
react-dom.development.js:86 Warning: Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.
at Navigate (http://localhost:3000/static/js/bundle.js:42950:5)
at Routes (http://localhost:3000/static/js/bundle.js:43067:5)
at div
at Router (http://localhost:3000/static/js/bundle.js:43000:15)
at BrowserRouter (http://localhost:3000/static/js/bundle.js:41809:5)
at App
Login.jsx
import { useState, useEffect } from "react";
import axios from "axios";
import { Link, useNavigate} from "react-router-dom";
const Login = () => {
const navigate = useNavigate();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
useEffect(() => {
if (localStorage.getItem("authToken")) {
navigate("/home");
}
}, [navigate]);
const loginHandler = async (e) => {
e.preventDefault();
const config = {
header: {
"Content-Type": "application/json",
},
};
try {
const { data } = await axios.post("/api/auth/login", { email, password }, config);
localStorage.setItem("authToken", data.token);
navigate("/home");
} catch (error) {
setError(error.response.data.error);
setTimeout(() => {
setError("");
}, 5000);
}
};
return (
<div className="login-">
<form onSubmit={loginHandler} className="login-__form">
<h3 className="login-__title">Login</h3>
{error && <span className="error-message">{error}</span>}
<div className="form-group">
<label htmlFor="email">Email:</label>
<input
type="email"
required
id="email"
placeholder="Email address"
onChange={(e) => setEmail(e.target.value)}
value={email}
tabIndex={1}
/>
</div>
<div className="form-group">
<label htmlFor="password">
Password:{" "}
{/* <Link to="/forgotpassword" className="login-__forgotpassword">
Forgot Password?
</Link> */}
</label>
<input
type="password"
required
id="password"
autoComplete="true"
placeholder="Enter password"
onChange={(e) => setPassword(e.target.value)}
value={password}
tabIndex={2}
/>
</div>
<button type="submit" className="btn btn-primary">
Login
</button>
<span className="login-__subtext">
Don't have an account? <Link to="/register">Register</Link>
</span>
</form>
</div>
);
};
export default Login;
AdminLogin.jsx
import { useState, useEffect } from "react";
import axios from "axios";
import { Link, useNavigate} from "react-router-dom";
const AdminLogin = () => {
const navigate = useNavigate();
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState("");
useEffect(() => {
if (localStorage.getItem("adminToken")) {
navigate("/admin/home");
}
}, [navigate]);
const adminLoginHandler = async (e) => {
e.preventDefault();
const config = {
header: {
"Content-Type": "application/json",
},
};
try {
const { data } = await axios.post("/api/admin/login", { username, password }, config);
localStorage.setItem("adminToken", data.token);
navigate("/admin/home");
} catch (error) {
setError(error.response.data.error);
setTimeout(() => {
setError("");
}, 5000);
}
};
return (
<div className="login-">
<form onSubmit={adminLoginHandler} className="login-__form">
<h3 className="login-__title">admin login</h3>
{error && <span className="error-message">{error}</span>}
<div className="form-group">
<label htmlFor="username">Username:</label>
<input
type="username"
required
id="username"
placeholder="Username"
onChange={(e) => setUsername(e.target.value)}
value={username}
tabIndex={1}
/>
</div>
<div className="form-group">
<label htmlFor="password">
Password:{" "}
{/* <Link to="/forgotpassword" className="login-__forgotpassword">
Forgot Password?
</Link> */}
</label>
<input
type="password"
required
id="password"
autoComplete="true"
placeholder="Enter password"
onChange={(e) => setPassword(e.target.value)}
value={password}
tabIndex={2}
/>
</div>
<button type="submit" className="btn btn-primary">
Login
</button>
<span className="login-__subtext">
Here by mistake? <Link to="/login">Login</Link>
</span>
</form>
</div>
);
};
export default AdminLogin;
it was asked in a comment, so i've also included Private.jsx (user home page) Admin.jsx (admin home page), though i don't think the issue is in either of these files.
Private.jsx
import { useState, useEffect } from "react";
import axios from "axios";
import { useNavigate } from "react-router-dom";
const Private = () => {
const [error, setError] = useState("");
const [privateData, setPrivateData] = useState("");
const navigate = useNavigate();
const handleLogout = () => {
localStorage.removeItem('authToken');
navigate('/login');
console.log('logged out successfully');
}
return error ? (
<span className="error-message">{error}</span>
) : (
<div>
you're in the private route
<button onClick = {handleLogout}>Logout</button>
</div>
);
};
export default Private;
Admin.jsx
import { useNavigate } from 'react-router-dom';
export default function Admin() {
const navigate = useNavigate();
const handleLogout = () => {
localStorage.removeItem('adminToken');
navigate('/admin/login');
console.log('logged out successfully');
}
return (
<>
<div>ADMIN ROUTE UNLOCKED</div>
<button onClick = {handleLogout}>Logout</button>
</>
)
}
You need to listen for changes in your localStorage. Try this:
const checkAuth = () => {
if (localStorage.getItem("authToken")) {
navigate("/home");
}
}
useEffect(() => {
window.addEventListener("storage", checkAuth);
return () => {
window.removeEventListener("storage", checkAuth)
}
}, []);
how to display to user an auth error differently than with alert?
For example: User will type a bad password, and a p tag will tell him, that he typed uncorrect password.
Using Firebase v9 and React.
Some code:
import React from 'react'
import { Link, useNavigate } from "react-router-dom";
import { UserAuth } from '../context/AuthContext';
import { useState } from 'react';
const Signin = () => {
const [email, setEmail] = useState('')
const [password, setPassword] = useState('')
const [error, setError] = useState('');
const navigate = useNavigate();
const { signIn } = UserAuth();
const handleSubmit = async (e) => {
e.preventDefault();
setError('')
try{
await signIn(email, password)
navigate("/");
} catch (e) {
setError(e.message)
alert(e.message)
}
}
return (
<div className='Signin'>Signin
<form onSubmit={handleSubmit}>
<label>Email</label>
<input onChange={(e) => setEmail(e.target.value)} type="email"/>
<label>password</label>
<input onChange={(e) => setPassword(e.target.value)} type="password"/>
<button type="submit">Sign up</button>
<p className='errorp'></p>
</form>
</div>
)
}
export default Signin
Thank you!
Something like {error && <p className='errorp'>{error}</p>}