Trying to implement user authorization through Firebase in a new React project.
import { User } from '@firebase/auth-types';
// ...
const [user, setUser] = useState<User | null>(null);
const auth = getAuth();
onAuthStateChanged(auth, (newUser) => {
setUser(newUser);
});
Error on setUser(newUser);
:
Argument of type 'User | null' is not assignable to parameter of type 'SetStateAction<User | null>'.
Type 'User' is not assignable to type 'SetStateAction<User | null>'.
Type 'User' is missing the following properties from type 'User': linkAndRetrieveDataWithCredential, linkWithCredential, linkWithPhoneNumber, linkWithPopup, and 14 more.ts(2345)
Tried doing newUser: User
which did not fix this error. Not sure what else to try as I'm very new to Typescript.
Entirety of this file:
import React, { useState } from 'react';
import { getAuth, onAuthStateChanged } from 'firebase/auth';
import { User } from '@firebase/auth-types';
function EmailPasswordForm(): JSX.Element {
const [isCreatingAccount, setIsCreatingAccount] = useState(false);
const createAccountForm = (
<>
<input placeholder="e-mail" />
<input placeholder="password" type="password" />
<input placeholder="confirm password" type="password" />
</>
);
const signInForm = (
<>
<input placeholder="e-mail" />
<input placeholder="password" type="password" />
</>
);
return (
<>
{isCreatingAccount ? createAccountForm : signInForm}
<button type="button">{isCreatingAccount ? 'create account' : 'sign in'}</button>
<button className="text-button" type="button" onClick={() => setIsCreatingAccount(!isCreatingAccount)}>
{isCreatingAccount ? 'i don\'t have an account!' : 'i already have an account!'}
</button>
</>
);
}
function SignIn(): JSX.Element {
const [user, setUser] = useState<User | null>(null);
const auth = getAuth();
onAuthStateChanged(auth, (newUser) => {
setUser(newUser);
});
if (user != null) {
return <span>you are signed in!</span>;
}
return (
<div className="center">
<EmailPasswordForm />
</div>
);
}
export default SignIn;
CodePudding user response:
The first thing that comes to the mind, is that this side effect should be done inside of useEffect, it should trigger when the component first mounts.
useEffect(() =>{
const unlisten = onAuthStateChanged(
authUser => {
authUser
? setAuthUser(authUser)
: setAuthUser(null);
},
);
return () => {
unlisten();
}
}, []);
and then clean up the effect. In my case exact same code works.
CodePudding user response:
Try this:
const [user, setUser] = useState<User | null>(null);
useEffect(() => {
const auth = getAuth();
const unsubscribe = onAuthStateChanged(auth, user => {
if (user) {
setUser(user);
}
});
// Don't listen on stateChange anymore if component did unmount.
return () => {
unsubscribe();
}
}, []);