Firebase phone sign-in, where to put firebase recaptcha code?
- The reason why it did not work in
componentWillMount
is because the container id you gave is not present in the dom yet. (will mount) - RecaptchaVerifier requires an empty div to be present for authentication. When you put the function inside render, it gets called again when the div will not be empty.
Now coming to the solution,
componentDidMount() {
window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier(this.recaptcha, {
'size': 'normal',
'callback': function (response) {
// reCAPTCHA solved, allow signInWithPhoneNumber.
// ...
},
'expired-callback': function () {
// Response expired. Ask user to solve reCAPTCHA again.
// ...
}
});
window.recaptchaVerifier.render().then(function (widgetId) {
window.recaptchaWidgetId = widgetId;
});
}
and in the HTML,
<div ref={(ref)=>this.recaptcha=ref}></div>
Instead of providing the id of the recaptcha div, we provide the reference of the DOM element (as is the practice in the React world), you can see the API of RecaptchaVerifier
for more information.
Or, with React.useRef
hook and TypeScript:
import React, {
useEffect
} from 'react';
import app from 'firebase/app';
import 'firebase/auth';
import 'firebase/analytics';
import 'firebase/firestore';
export const LoginScreen: React.FunctionComponent = () => {
const app: app.app.App | null = app.initializeApp();
const captchaRef = React.useRef(null);
const OnPressLogin = async(phone: string) => {
this.auth ? .signInWithPhoneNumber(
phone,
new app.auth.RecaptchaVerifier(captchaRef.current, {
size: 'invisible',
callback: (response: any) => {
console.info('Invisible Captcha', response);
// reCAPTCHA solved, allow signInWithPhoneNumber.
onCaptcha();
},
}),
);
};
return ( <>
<div id="recaptcha-container" ref={captchaRef}></div>
<LoginForm disabled={isBusy} onSubmit={OnPressLogin} />
);
};