Я использую Firebase в качестве серверной части для разработки приложения реагирования. Также я использую onAuthStateChanged
firebase в качестве наблюдателя для отслеживания изменений состояния пользователя.
App.tsx
const App: React.FC = () => {
const [authentication, setAuthState] = useState({
authenticated: !!auth.currentUser,
initializing: true,
emailVerified: auth.currentUser ? auth.currentUser.emailVerified : false,
});
React.useEffect(() => auth.onAuthStateChanged(user => {
//TODO need to handle authorization here
console.log("Auth state changed!", user);
if (user) {
setAuthState({
authenticated: true,
initializing: false,
emailVerified: user.emailVerified
});
} else {
setAuthState({
authenticated: false,
initializing: false,
emailVerified: false
});
}
}), [setAuthState]);
if (authentication.initializing) {
return <div style={{textAlign: 'center', paddingTop: '5%'}}>
<div style={{display: 'inline-block'}}>
<Spin/>
</div>
</div>
}
//TODO if already loggedin navigate without loading
// if(authentication.authenticated){
// return <Redirect to="/nav"/>;
// }
return (
<BrowserRouter>
<div>
<Switch>
<PublicRoute path="/" component={Welcome} exact isAuthorized={true}/>
<PublicRoute path="/login" component={NewLogin} exact isAuthorized={true}/>
<PrivateRoute path="/nav" component={NavigationBar} exact isSignedIn={authentication.authenticated}/>
<PrivateRoute path="/onboarding" component={OnBoarding} exact isSignedIn={authentication.authenticated}/>
</Switch>
</div>
</BrowserRouter>
);
};
export default App;
newlogin.tsx
const MyLogin: React.FC = (props: any) => {
const {getFieldDecorator} = props.form;
const history = useHistory();
let [loginState, setLoginState] = useState({
loading:false,
loggedIn:!!auth.currentUser
});
const buttonStyle = {
width: '100%',
height: '40px',
};
const handleSuccessfulLogin = () => {
console.log("coming for successful login");
message.success("Login Successful!");
setLoginState({
loading:false,
loggedIn:true
});
}
const handleCreate = (e: any) => {
console.log("coming for signup");
e.preventDefault();
props.form.validateFields(['signupName', 'signupMail', 'signupPassword'], (err: any, values: object) => {
if (!err) {
console.log('Received values of form:', values);
}
});
}
const handleLogin = (e: any) => {
e.preventDefault();
setLoginState({
loading: true,
loggedIn: false
});
console.log("coming for login");
props.form.validateFields(['loginMail', 'loginPassword'], (err: object, values: object) => {
if (err) {
return;
}
auth
.setPersistence(session_type)
.then(() => console.log('state set successfully!!'))
.catch(function (error) {
console.log("Error in setting persistence", error.code, '-', error.message);
});
// @ts-ignore
auth.signInWithEmailAndPassword(values.loginMail, values.loginPassword)
.then(handleSuccessfulLogin)
.catch(function (error) {
message.error(error.code + ' - ' + error.message);
console.log('Sign in failed!', error.code, ' and ', error.message);
setLoginState({
loading: false,
loggedIn: false
});
});
});
}
if (loginState.loading){
return <div style={{textAlign: 'center', paddingTop: '5%'}}>
<div style={{display: 'inline-block'}}>
<Spin/>
</div>
</div>
}
if(loginState.loggedIn){
// @ts-ignore
console.log("Planning to redirect since loggedin: ", auth.currentUser.emailVerified);
history.push("/nav");
}
console.log("--> coming after history push");
return (
<div>
<Form onSubmit={handleLogin}>
<Form.Item>
{getFieldDecorator('loginMail', {
rules: [
{
required: true,
message: 'Please enter valid email address',
type: 'email'
}
]
})(<Input
prefix={<Icon type="mail"/>}
placeholder="Email"
style={buttonStyle}
/>)}
</Form.Item>
<Form.Item>
{getFieldDecorator('loginPassword', {
rules: [
{
required: true,
message: 'Please enter password'
}
]
})(<Input.Password
prefix={<Icon type="lock"/>}
type="password"
placeholder="Password"
style={buttonStyle}
/>)}
</Form.Item>
<Form.Item>
<Checkbox style={{float: 'left'}}>Remember me</Checkbox>
<a href="" style={{float: 'right'}}>
Forgot password
</a>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" style={buttonStyle}>
Login
</Button>
</Form.Item>
<Form.Item>
<Divider>or connect with</Divider>
<Divider>
<div style={{maxHeight: '3em'}}>
<Icon type="google" style={{fontSize: '2.5em', color: '#1890ff'}}/>
</div>
</Divider>
</Form.Item>
</Form>
</div>
);
}
export const NewLogin = Form.create()(MyLogin);
С помощью приведенного выше кода я могу аутентифицировать URL и его работоспособность как в состоянии входа в систему, так и в состоянии выхода из системы.
Этот код работает абсолютно нормально, за исключением одного сценария, в котором я пытаюсь перейти на целевую страницу после входа в систему.
Когда я пытаюсь перенаправить через useHistory
ловушку, я вижу, что он идет бесконечно зацикливается и в конечном итоге уничтожается реакцией.
Я правильно изменяю состояние и не уверен, где оно идет не так.
Это ошибка, которую я получаю,