I'm trying to use the reCaptcha integrated in firebase authentication with React and Redux.
const Login = props => {
useEffect(() => {
window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('login-button', {
'size': 'invisible',
'callback': () => login()
}
);
window.recaptchaVerifier.render()
}, []);
function login() {
console.log(props)
firebaseLogin(props.email, props.password).then(() => {
...
}
).catch(function (error) {
console.log(error);
...
});
}
function onChangePassword(event) {
props.onChangePassword(event.target.value)
}
function onChangeEmail(event) {
props.onChangeEmail(event.target.value)
}
return (
...
<form>
<label>Dirección de Email</label>
<div className="form-group">
<input type="email"
className={`form-control ${emailValidation ? "is-invalid" : ""}`}
placeholder="nombre@mail.com"
onChange={onChangeEmail} value={props.email} tabIndex={1}
autoComplete={"username"}
required/>
<div className="invalid-feedback">
{emailValidation}
</div>
</div>
<div className="form-group">
<div className="row">
<div className="col">
<label>Contraseña</label>
</div>
<div className="col-auto">
<Link to="/reset-password" className="form-text small text-muted">
Olvidé mi contraseña
</Link>
</div>
</div>
<div className="input-group input-group-merge">
<input type={showPassword ? "text" : "password"}
className={`form-control ${passwordValidation ? "is-invalid" : ""} form-control-appended`}
placeholder="Ingrese su contraseña" onChange={onChangePassword}
value={props.password} required tabIndex={2}
autoComplete={"current-password"}/>
<div className="input-group-append">
<span className="input-group-text clickable"
onClick={() => setShowPassword(!showPassword)}>
<i className="fe fe-eye"/>
</span>
</div>
<div className="invalid-feedback">
{passwordValidation}
</div>
</div>
</div>
<button type="submit" className="btn btn-lg btn-block btn-primary mb-3"
id={"login-button"}
tabIndex={3}>
Acceder
</button>
</form>
...
)
};
const mapDispatchToProps = dispatch => ({
onChangeEmail: value =>
dispatch({type: UPDATE_LOGIN_FIELD, key: 'formEmail', value}),
onChangePassword: value =>
dispatch({type: UPDATE_LOGIN_FIELD, key: 'password', value}),
});
const mapStateToProps = state => ({
email: state.authentication.formEmail,
password: state.authentication.password,
});
export default connect(mapStateToProps, mapDispatchToProps)(Login);
The problem is that in the login callback the props are outdated and doesn't contain the email and password that are loaded in the redux store, it just contains the props that were available when the useEffect was triggered. (I see that with the console.log(props))
I don't know how can I keep a reference to the updated props. I've tried using the useRef hook and sending it to the login as a parameter, but that didn't work either.
I've also tried using the email and password props as useEffect dependencies, but that triggers the recaptcha generation a lot of times and it's very inefficient.
Thanks for your help!
Seems to work as
window.login = useCallback(() => {
console.log(props);
firebaseLogin(props.email, props.password).then(() => {
...
}
).catch(function (error) {
console.log(error);
....
}
}, [props]);
useEffect(() => {
window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('login-button', {
'size': 'invisible',
'callback': () => window.login(),
}
);
window.recaptchaVerifier.render();
}, []);
There is another problem, but not related to this question