Пытаемся реализовать авторизацию пользователя через Firebase в новом проекте React.
import { User } from '@firebase/auth-types';
// ...
const [user, setUser] = useState<User | null>(null);
const auth = getAuth();
onAuthStateChanged(auth, (newUser) => {
setUser(newUser);
});
Ошибка на setUser(newUser);
:
Аргумент типа «Пользователь | null» нельзя присвоить параметру типа >'SetStateAction<User | ноль>'. Тип «Пользователь» не может быть назначен типу «SetStateAction<User | ноль>'. В типе «Пользователь» отсутствуют следующие свойства типа «Пользователь»: linkAndRetrieveDataWithCredential, linkWithCredential, linkWithPhoneNumber, linkWithPopup и еще 14.ts(2345)
Пробовал делать newUser: User
, что не исправило эту ошибку. useState<any | null>
решает эту проблему, но я считаю, что это противоречит цели Typescript.
newUser: React.SetStateAction<User | null>
приводит к другой ошибке:
Аргумент типа «(newUser: React.SetStateAction<User | null>) => void» не может быть назначен параметру типа «NextOrObserver». Тип «(newUser: React.SetStateAction<User | null>) => void» не может быть назначен типу «NextFn<User | ноль>'. Типы параметров newUser и value несовместимы. Введите «Пользователь | null» нельзя присвоить типу «SetStateAction<User | ноль>'. Тип «Пользователь» не может быть назначен типу «SetStateAction<User | ноль>'. В типе «Пользователь» отсутствуют следующие свойства типа «Пользователь»: linkAndRetrieveDataWithCredential, linkWithCredential, linkWithPhoneNumber, linkWithPopup и еще 14.ts(2345)
Я считаю, что это просто предупреждения, так как все по-прежнему работает правильно, но я хотел бы решить эту проблему, несмотря ни на что. Не уверен, что еще попробовать, так как я очень новичок в Typescript.
Весь этот файл:
import React, { useState, useEffect } from 'react';
import { getAuth, onAuthStateChanged, createUserWithEmailAndPassword, signInWithEmailAndPassword } from 'firebase/auth';
import { User } from '@firebase/auth-types';
function EmailPasswordForm(): JSX.Element {
const [isCreatingAccount, setIsCreatingAccount] = useState(false);
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const auth = getAuth();
const onButtonClick = () => {
if (isCreatingAccount) {
createUserWithEmailAndPassword(auth, email, password)
.catch((error) => {
console.info(error.code, error.message);
});
} else {
signInWithEmailAndPassword(auth, email, password)
.catch((error: { code: any; message: any; }) => {
console.info(error.code, error.message);
});
}
}
const onEmailChange = (e: { target: { value: React.SetStateAction<string>; }; }) => setEmail(e.target.value);
const onPasswordChange = (e: { target: { value: React.SetStateAction<string>; }; }) => setPassword(e.target.value);
const onConfirmPasswordChange = (e: { target: { value: React.SetStateAction<string>; }; }) => setConfirmPassword(e.target.value);
const createAccountForm = (
<>
<input placeholder = "e-mail" onChange = {onEmailChange} />
<input placeholder = "password" type = "password" onChange = {onPasswordChange} />
<input placeholder = "confirm password" type = "password" onChange = {onConfirmPasswordChange} />
</>
);
const signInForm = (
<>
<input placeholder = "e-mail" onChange = {onEmailChange} />
<input placeholder = "password" type = "password" onChange = {onPasswordChange} />
</>
);
return (
<>
{isCreatingAccount ? createAccountForm : signInForm}
<button type = "button" onClick = {onButtonClick}>{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;
🤔 А знаете ли вы, что...
React - это библиотека JavaScript, разработанная компанией Facebook.
Первое, что приходит на ум, это то, что этот побочный эффект должен быть реализован внутри useEffect, он должен срабатывать при первом монтировании компонента.
useEffect(() =>{
const unlisten = onAuthStateChanged(
authUser => {
authUser
? setAuthUser(authUser)
: setAuthUser(null);
},
);
return () => {
unlisten();
}
}, []);
а затем очистить эффект. В моем случае работает точно такой же код.
Попробуй это:
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();
}
}, []);
Обновлять:
Вы должны импортировать пользовательский интерфейс из «firebase/auth», а не «@firebase/auth-types»;
import { User } from "firebase/auth";