我正在尝试将React和Redux集成在Firebase身份验证中的reCaptcha。
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="[email protected]"
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);
问题是,在登录回调中,道具已经过时,并且不包含在redux存储中加载的电子邮件和密码,它仅包含触发useEffect时可用的道具。 (我通过console.log(props)看到了)
我不知道如何保留对更新道具的引用。我尝试使用useRef挂钩并将其作为参数发送到登录名,但这也不起作用。
我也尝试过使用电子邮件和密码道具作为useEffect依赖项,但是这多次触发了Recaptcha生成,而且效率很低。
感谢您的帮助!
使用回调挂钩以高性能的方式访问最新状态。
const login = useCallback( () => {
console.log(props)
firebaseLogin(props.email, props.password).then(() => {
...
}
).catch(function (error) {
console.log(error);
...
});
}, [ props ] ):
在官方的React文档上,它声明:“传递一个内联回调和一系列依赖项。useCallback将返回该回调的记录版本,只有在其中一个依赖项发生更改时,该回调版本才会更改。”在我们的例子中,每次[props]
更改时,登录功能都会自动更新,这意味着当我们获得新的道具时,我们将获得一个新的登录功能。
查看官方hook documentation,以获取有关如何使用哪个钩子的更多信息。
您甚至可以将useCallback
用于所有三个功能!
const onChangePassword = useCallback( (event) => {
props.onChangePassword(event.target.value)
}, [props.onChangePassword]);
const onChangeEmail = useCallback( (event) => {
props.onChangeEmail(event.target.value)
}, [props.onChangeEmail]);
onChangePassword
和onChangeEmail
回调函数将在每次从Redux或更高阶组件更新props.onChangePassword
和props.onChangeEmail
函数时更新并创建新函数。
似乎起
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();
}, []);
还有另一个问题,但与此问题无关