Firebase won't register user information - reactjs

Firebase isn't registering my user's information.
I keep getting a warning saying: 'onAuthStateChanged' is defined but never used and
'user' is assigned a value but never used.
Also, when I enter the email and password it doesn't set to empty string even though I set my password and email both to ("").
import './App.css';
import { auth } from './firebase';
import { useState, useEffect } from 'react';
import {
signInWithEmailAndPassword,
onAuthStateChanged, //<-----Here's my problem
createUserWithEmailAndPassword,
} from 'firebase/auth';
function App() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [user, setUser] = useState([]); // <---------Here is the other issue
const [isSignUp, setIsSignUp] = useState(false);
useEffect(() => {
auth.onAuthStateChanged((user) => {
setUser(user);
});
});
const handleEmailChange = (e) => {
setEmail(e.target.value);
};
const handlePasswordChange = (e) => {
setPassword(e.target.value);
};
const signIn = async () => {
await signInWithEmailAndPassword(auth, email, password)
.then(() => {
setEmail('');
setPassword('');
})
.catch((error) => {
alert(error.message);
});
};
const register = async () => {
await createUserWithEmailAndPassword(auth, email, password).catch((error) =>
console.log(error.message)
);
setPassword('');
setEmail('');
};
return (
<div className="App">
{isSignUp ? (
<>
<h1>Registering...</h1>
<input
type="email"
placeholder="email"
value={email}
onChange={handleEmailChange}
/>
<input
type="password"
placeholder="password"
value={password}
onChange={handlePasswordChange}
/>
<button onClick={register}>Sign Up</button>
<button onClick={() => setIsSignUp(false)}>X</button>
</>
) : (
<>
<h1>Logging in...</h1>
<input
type="email"
placeholder="email"
value={email}
onChange={handleEmailChange}
/>
<input
type="password"
placeholder="password"
value={password}
onChange={handlePasswordChange}
/>
<button onClick={signIn}>Login</button>
<button onClick={() => setIsSignUp(true)}>Register</button>
</>
)}
</div>
);
}
export default App;

I see two mistakes.
First, you should use the modular syntax for your auth state handler:
useEffect(() => {
onAuthStateChanged((user) => { // 👈 Remove the auth. here
setUser(user);
});
});
And second, the default value of the user is an object, not an array:
const [user, setUser] = useState({});
There may be more problems, but these jumped out at me.

The actual solution to my problem was that I was in the wrong app in Firebase. Once I selected the right one from the dropdown menu it worked.

Related

I try to sign up and then login but it not working giving error in react using firebase data base with auth?

I try to sign up and log in react through fire base auth but it show error on both form.
When I try to Signup it give error 'Field to create account' And when I try to login it also give error 'Filed to login' kindly review below code. Where I make mistake??
this is context.js
import React, { useContext, useState, useEffect } from "react"
import { auth } from "../Firebase/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 && children}
</AuthContext.Provider>
)
}
This is Signup.js
function Signup() {
const emailRef = useRef()
const passwordRef = useRef()
const passwordConfirmRef = useRef()
const { signup } = useAuth()
const [error, setError] = useState("")
const [loading, setLoading] = useState(false)
const navigate = useNavigate ()
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)
navigate.push("/")
} catch {
When I try this error show
setError("Failed to create an account")
}
setLoading(false)
}
return (
<>
<Form onSubmit={handleSubmit} >
<Form.Group id="email">
<Form.Label>Email</Form.Label>
<Form.Control type="email" ref={emailRef} required />
</Form.Group>
<Form.Group id="password">
<Form.Label>Password</Form.Label>
<Form.Control type="password" ref={passwordRef} required />
</Form.Group>
<Form.Group id="password-confirm">
<Form.Label>Password Confirmation</Form.Label>
<Form.Control type="password" ref={passwordConfirmRef} required />
</Form.Group>
<Button disabled={loading} type="submit">
Sign Up
</Button>
</Form>
</>
)
}
export default Signup
This is Login.js
function Login() {
const emailRef = useRef()
const passwordRef = useRef()
const { login } = useAuth()
const [error, setError] = useState("")
const [loading, setLoading] = useState(false)
const navigate = useNavigate ()
async function handleSubmit(e) {
e.preventDefault()
try {
setError("")
setLoading(true)
await login(emailRef.current.value, passwordRef.current.value)
navigate.push("/")
} catch {
This error show when I try
setError("Failed to log in")
}
setLoading(false)
}
return (
<>
<Form onSubmit={handleSubmit} >
<Form.Group id="email">
<Form.Label>Email</Form.Label>
<Form.Control type="email" ref={emailRef} required />
</Form.Group>
<Form.Group id="password">
<Form.Label>Password</Form.Label>
<Form.Control type="password" ref={passwordRef} required />
</Form.Group>
<Button disabled={loading} type="submit">
Log In
</Button>
</Form>
</>
)
}
export default Login
Kindly anyone can review my code where I make mistake??

retrieve store data from react redux

I'm new to redux, I can't get data from the store.I get this message in the console:
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
thank you in advance for help.
reducer
import { CONNECT_CLIENT, GET_CLIENT } from "../action/Action";
export const initialClient = {
email: "",
password: ""
}
export default function ConnectClient (state = initialClient, action= {}){
switch (action.type) {
case CONNECT_CLIENT:
console.log(action.payload);
return {
...state,
client: [action.payload]
}
case GET_CLIENT:
return {
...state,
initialClient: action.initialClient
}
default:
break;
}
}
clientService
export const ConnectClient = () =>{
const {initialClient } = useSelector(state => state)
console.log(initialClient)
const dispatch = useDispatch();
dispatch({
type: GET_CLIENT,
initialClient: initialClient
})
return new Promise((resolve, reject)=>{
axios.post('http://localhost:3000/api/client/loginClient',{
initialClient: initialClient
})
.then((response, error)=>{
if(!response || error) {
return reject(`Response rejected: ${error}`);
}
resolve(response);
})
})
}
Form connection
const Connexion = () =>{
const dispatch = useDispatch();
const [email, setEmail] = useState("")
const [password, setPassword] =useState("")
const submit=(e)=>{
e.preventDefault();
ConnectClient().then(response => console.log(response))
console.log(email)
console.log(password)
dispatch({
type: CONNECT_CLIENT,
payload: {email, password}
})
}
return (
<form className="container-connexion" model="client">
<div className="container-email-password">
<div className="email">
<label htmlFor="email">Email</label>
<input id="email" type="email" value={email} onChange={(e)=> setEmail(e.target.value)} name="email" required/>
</div>
<div className="password">
<label htmlFor="password">Mot de passe</label>
<input type="password" value={password} name="password" onChange={(e)=> setPassword(e.target.value)} required/>
</div>
</div>
<div className="container-btn-connexion">
<button className="btn-connexion" onClick={submit} >Se connecter</button>
<button className="btn-inscription">Inscription</button>
</div>
</form>
)
}
We can only call hooks inside the body of functional components, or in the body of custom hooks. Your ConnectClient function is neither of those.
One solution is calling the useDispatch and useSelector hooks in the Connexion component, and passing initialClient and dispatch to the ConnectClient function as parameters.
export const ConnectClient = (dispatch, initialClient) => {
dispatch({
type: GET_CLIENT,
initialClient: initialClient,
});
return new Promise((resolve, reject) => {
axios.post('http://localhost:3000/api/client/loginClient', {
initialClient: initialClient,
}).then((response, error) => {
if(!response || error) {
return reject(`Response rejected: ${error}`);
}
resolve(response);
});
});
};
const Connexion = () =>{
const dispatch = useDispatch();
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const { initialClient } = useSelector(state => state);
const submit=(e)=>{
e.preventDefault();
ConnectClient(dispatch, initialClient).then(response => console.log(response));
dispatch({
type: CONNECT_CLIENT,
payload: {email, password}
})
}
return (
<form className="container-connexion" model="client">
<div className="container-email-password">
<div className="email">
<label htmlFor="email">Email</label>
<input id="email" type="email" value={email} onChange={(e)=> setEmail(e.target.value)} name="email" required/>
</div>
<div className="password">
<label htmlFor="password">Mot de passe</label>
<input type="password" value={password} name="password" onChange={(e)=> setPassword(e.target.value)} required/>
</div>
</div>
<div className="container-btn-connexion">
<button className="btn-connexion" onClick={submit} >Se connecter</button>
<button className="btn-inscription">Inscription</button>
</div>
</form>
);
}

Cannot register. Username and password did not pass in the payload when using useRef

I tried to pass the username and password input by using useRef() for the registration process through the register form. After click button to submit it, it said required username and password. I check the network payload at browser, it only contain email without username and password.
Below are the code
import { useRef, useState } from "react";
import "./register.scss";
import axios from "axios";
import { useNavigate } from "react-router-dom";
const Register = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [username, setUsername] = useState("");
const navigate = useNavigate();
const emailRef = useRef();
const passwordRef = useRef();
const usernameRef = useRef();
// Send email to appear password
const handleStart = () => {
setEmail(emailRef.current.value);
};
// Send username & password for membership
const handleFinish = async (e) => {
e.preventDefault();
setPassword(passwordRef.current.value);
setUsername(usernameRef.current.value);
try {
await axios.post("auth/register", { username, email, password });
navigate("/login");
} catch (err) {
console.log(err);
}
};
return (
<div className="register">
<div className="wrapper">
<div className="header">
<img src="./assets/logo.png" alt="" className="logo" />
<button className="login-btn">Sign In</button>
</div>
</div>
<div className="container">
<h1>Unlimited movies, TV shows and more</h1>
<h2>Watch anywhere. Cancel anytime.</h2>
<p>
Ready to watch? Enter your email to create or restart your membership.
</p>
{!email ? (
<div className="input">
<input type="email" placeholder="Email address" ref={emailRef} />
<button className="register-btn" onClick={handleStart}>
Get Started
</button>
</div>
) : (
<form className="input">
<input type="username" placeholder="Username" ref={usernameRef} />
<input type="password" placeholder="Password" ref={passwordRef} />
<button className="register-btn" onClick={handleFinish}>
Start
</button>
</form>
)}
</div>
</div>
);
};
export default Register;
Here are the screenshot for network payload
Payload
[Preview2
You're trying to access state that hasn't update yet.
If you're using refs, you can remove the useState hooks and change your code to something like below.
const handleFinish = async (e) => {
e.preventDefault();
try {
await axios.post("auth/register", { username: usernameRef.current.value , email: emailRef.current.value, password: passwordRef.current.value });
navigate("/login");
} catch (err) {
console.log(err);
}
Controlled components would be a better option for handling form elements imo.
https://reactjs.org/docs/forms.html#controlled-components

Change multiple elements simultaneously

I have a button which upon clicking, should make the password field blank. I also intend to change the text of the button from Change Password to Save password at the same time. In short, I would like these changes to happen at the same time. I have taken a toggle variable using which I'm able to change the text of the button but do not know how to do the same for the password field.
Here is my code:
import { useState } from "react";
import { useHistory } from "react-router";
const User = () => {
const [username, setUsername] = useState()
const [password, setPassword] = useState()
const [toggle, setToggle] = useState(false);
const history = useHistory();
const login = () => {
// if (username === 'admin' & password === 'admin') {
// history.push('/home')
// } else {
// alert('wrong credentials')
// }
setToggle(!toggle);
}
return (
<>
<div className="container">
<label for="username">UserName:</label>
<input
className="form-control"
type='text'
id="username"
name="username"
value={username}
onChange={(evt) => setUsername(evt.target.value)}
/>
<br />
<label for="password">Password:</label>
<input
className="form-control"
type='text'
id="password"
name="password"
value={password}
onChange={(evt) => setPassword(evt.target.value)}
/>
<button className="btn btn-primary mt-5 " onClick={login}>{toggle ? 'SavePassword' : ' change password '}</button>
<button className="btn btn-primary mt-5 ml-5 pull-right" onClick={login}>Log out</button>
</div>
</>
)
}
export default User;
Fastest answer is:
const login = () => {
setPassword('');
setToggle(!toggle);
}
This solution has a problem: every time you run login function your component is re-rendered twice.
To avoid this, there are several ways; the first one could be join username, password and toggle into the same state. Something like:
const [state, setState] = useState({
username: null,
password: null,
toggle: false
});
...
const login = () => {
setState((prevState) => {
return {
toggle: !prevState.toggle,
username: prevState.username
password: "",
}
});
}

Two times click is necessary to Login in ReactJS

I am trying to make a Login page and I am successful in some way. So here is my Login component:
import React, { useState, useEffect } from "react";
import Axios from "axios";
import useForm from "../components/LoginForm/useForm";
import validate from "components/LoginForm/validate";
import redtruck from "../assets/img/red-truck.png";
import auth from "../Authentication/auth";
import { withRouter } from "react-router";
const Login = ({ submitForm, history }) => {
const [isSubmitted, setIsSubmitted] = useState(false);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(false);
const [login, setLogin] = useState(false);
async function submitForm() {
setIsSubmitted(true);
try {
await fetchLogin(values.email, values.password);
if(login){
auth.login(() => {
history.push("/admin");
});
}
} catch (e) {
auth.login(() => {
history.push("/");
})
}
}
const { handleChange, values, handleSubmit, errors } = useForm(
submitForm,
validate
);
useEffect(() => {
if (localStorage.getItem("user-info")) {
submitForm();
}
}, []);
const fetchLogin = async (email, password) => {
try {
setLoading(true);
const res = await Axios({
method: "POST",
url: `url`,
headers: {
},
data: {
user_email: email,
user_password: password,
},
});
if (res.status === 200) {
setLogin(true);
localStorage.setItem("user-info", JSON.stringify(res.data));
}
setLoading(false);
} catch (err) {
setError(err.message);
setLoading(false);
}
};
return (
<>
<div>
<div className="form-container">
<div className="form-content-left">
<img className="form-img" src={redtruck} alt="spaceship" />
</div>
<div className="form-content-right">
<h1>SIGN IN</h1>
<form className="form" onSubmit={handleSubmit}>
<div className="form-inputs">
<label htmlFor="email" className="form-label">
Email address
</label>
<input
id="signin-email"
type="email"
name="email"
placeholder="Enter email"
className="form-input"
value={values.email}
onChange={handleChange}
/>
{errors.email && <p>{errors.email}</p>}
</div>
<div className="form-inputs">
<label htmlFor="password" className="form-label">
Password
</label>
<input
id="signin-password"
type="password"
name="password"
placeholder="Password"
className="form-input"
value={values.password}
onChange={handleChange}
/>
{errors.password && <p>{errors.password}</p>}
{login ? "" : <p>The password or the email is wrong</p>}
</div>
<button
variant="primary"
type="submit"
className="form-input-btn"
>
LOGIN
</button>
</form>
</div>
</div>
</div>
</>
);
};
export default withRouter(Login);
So the login state is set to true when email and password are right for the user. Later I want to use it when redirecting page to "/admin". But my problem is I have to click twice to login in the first place. Besides I am not sure, if the catch part is right:
catch (e) {
auth.login(() => {
history.push("/");
})
}
So I would be really glad, if you can give me some hint about it.
Thanks...
it is not that you have to press twice, you can check component state, sometimes React batches setState and then update value. You can look at this setState doesn't update the state immediately

Resources