t49tran / react-google-recaptcha-v3

Google Recaptcha V3 integration for React
MIT License
435 stars 91 forks source link

onVerify is not calling in subsequent rendering of the same react component #41

Closed JudeNiroshan closed 4 years ago

JudeNiroshan commented 4 years ago

I have a simple LoginForm component. This is how I have wrapped my component with GoogleReCaptchaProvider component.

render() {
    console.log("calling rendering")
    return (
      <GoogleReCaptchaProvider reCaptchaKey={this.state.recapcharKey}>
        <GoogleReCaptcha onVerify={this.onVerifyCallback} action={"login"}/>
        <div className="form trial-form ml-md-auto">
          ...
        </div>
      </GoogleReCaptchaProvider>
    )
  }

This is my callback function that I submitted for onVerify()

  onVerifyCallback(token) {
    console.log("token received!")
    this.setState({token: token, btnDisable: false, btnTxt: 'Login'})
  }

Problem:

At the initial when the page is rendering, I can see the onVerifyCallback has being triggered. But if I move to a different page(home page) without refreshing my web page, and then come back to login page(which has this shown code) will not trigger the onVerifyCallback method.

Output I see on the browser console:

index.js:1 Timeout (n)
console.<computed> @ index.js:1
(anonymous) @ VM5305 recaptcha__en.js:28
Promise.catch (async)
(anonymous) @ VM5305 recaptcha__en.js:28
(anonymous) @ VM5305 recaptcha__en.js:304
next @ VM5305 recaptcha__en.js:335
(anonymous) @ VM5305 recaptcha__en.js:34
(anonymous) @ VM5305 recaptcha__en.js:34
(anonymous) @ VM5305 recaptcha__en.js:81
(anonymous) @ VM5305 recaptcha__en.js:28
(anonymous) @ VM5305 recaptcha__en.js:344
(anonymous) @ google-recaptcha-provider.tsx:85
Promise.then (async)
(anonymous) @ google-recaptcha-provider.tsx:84
step @ index.js:1
(anonymous) @ index.js:1
(anonymous) @ index.js:1
__awaiter @ index.js:1
GoogleReCaptchaProvider._this.executeRecaptcha @ google-recaptcha-provider.tsx:81
(anonymous) @ google-recaptcha.tsx:22
step @ index.js:1
(anonymous) @ index.js:1
(anonymous) @ index.js:1
__awaiter @ index.js:1
GoogleReCaptcha.componentDidMount @ google-recaptcha.tsx:13
commitLifeCycles @ react-dom.development.js:19814
commitLayoutEffects @ react-dom.development.js:22803
callCallback @ react-dom.development.js:188
invokeGuardedCallbackDev @ react-dom.development.js:237
invokeGuardedCallback @ react-dom.development.js:292
commitRootImpl @ react-dom.development.js:22541
unstable_runWithPriority @ scheduler.development.js:653
runWithPriority$1 @ react-dom.development.js:11039
commitRoot @ react-dom.development.js:22381
finishSyncRender @ react-dom.development.js:21807
performSyncWorkOnRoot @ react-dom.development.js:21793
(anonymous) @ react-dom.development.js:11089
unstable_runWithPriority @ scheduler.development.js:653
runWithPriority$1 @ react-dom.development.js:11039
flushSyncCallbackQueueImpl @ react-dom.development.js:11084
flushSyncCallbackQueue @ react-dom.development.js:11072
discreteUpdates$1 @ react-dom.development.js:21893
discreteUpdates @ react-dom.development.js:806
dispatchDiscreteEvent @ react-dom.development.js:4168
index.js:1 Uncaught (in promise) Timeout (n)

Am I doing/using something wrong?

t49tran commented 4 years ago

@JudeNiroshan , thanks for reporting that. I will have a look when I have time.

JudeNiroshan commented 4 years ago

It seems like https://github.com/t49tran/react-google-recaptcha-v3/blob/24cfcb9391ec7fe5eccbec2c5098df3c02e70b53/src/google-recaptcha.tsx#L22 is not firing on component re-render

t49tran commented 4 years ago

Yeah, that's expected behaviour for that component, it's only run once on componentDidMount. You don't want it to fire on every single re-render though. You might want to track that.

Your code looks ok to me except that you should put GoogleRecaptchaProivder on top level of your application. This component should only be rendered once for the whole application.

JudeNiroshan commented 4 years ago

Thank you. But usually customers do not want to show the recaptcha logo on every page on the website. For example, home page.

Google reCaptcha v2 is about adding a different kind of form input. Now the enhanced version(v3) will not add a form input attribute rather secretly validate the user. Basically reCaptcha is used for input forms of a website.

IMO, adding the GoogleReCaptchaProvider to wrap the entire react app, is not the intended usage of Google reCaptcha.

t49tran commented 4 years ago

@JudeNiroshan , you can hide the Google Logo if you want.

The reason why GoogleReCaptchaProvider should stay at the top level of the app, or the page has nothing to do with the intended usage of Google reCaptcha. It's a provider component that does two things: load the Google Recaptcha script and provide a React context value that including common recaptcha functions. For any application, to avoid errors, you only want to perform both these two tasks once.

Also, it's Google decision that by just including the recaptcha v3 script into your page, the logo will be displayed. So, if you use vanilla Javascript and not React, the same thing will happen. It's intended behaviour from Google.

Having said that, it doesn't seem that your problem is caused by where you place GoogleReCaptchaProvider.

t49tran commented 4 years ago

This problem has been resolved in v1.6.1 #45