dozoisch / react-google-recaptcha

Component wrapper for Google reCAPTCHA
MIT License
1.02k stars 142 forks source link

Executing Invisible reCAPTCHA, value is a null string #35

Closed Sawtaytoes closed 7 years ago

Sawtaytoes commented 7 years ago

When using an invisible captcha, I'm doing this.captcha.execute() on submit. My onChange handler isn't called and in the onSubmit, when I do this.captcha.getValue(), the value is a null string. What could cause this?

dozoisch commented 7 years ago

Is your captcha configured to be an invisible captcha? (on google side)

yanivefraim commented 7 years ago

@Sawtaytoes - this is how I do it, and it works for me:

<ReCAPTCHA
    ref={el => this.captcha = el}
    size="invisible"
    sitekey={getSiteKey()}
    onChange={token => this.submitForm(token)}
    />

<Button onClick={() => this.captcha.execute()}>
      Submit
</Button>
Sawtaytoes commented 7 years ago

Ah, this is different in some way. I'm calling a handler onSubmit which then calls execute(), but in the same process, it's calling the setState and doing a Relay call. At what point would I see something in .getValue()? When debugging, I never saw that value populated when doing a .execute().

Another difference is I've got my ReCAPTCHA component wrapped by a functional abstracting Captcha component. could it be having issues because ReCAPTCHA isn't on the page directly and the wrapper component is functional?

const InvisibleCaptcha = ({ getRef, onChange, onExpire, onLoad, tabIndex }) => {
    return (<ReCAPTCHA
        ref={getRef}
        sitekey={config.googleInvisibleRecaptchaSiteKey}
        size="invisible"
        theme="dark"
        tabIndex={tabIndex}
        asyncScriptOnLoad={onLoad}
        onChange={onChange}
        onExpired={onExpire}
    />);
};

And used like this:

{showCaptcha && <InvisibleCaptcha
    getRef={this.storeCaptchaElement.bind(this)}
    onChange={this.handleRecaptchaSubmission.bind(this)}
    onExpire={this.handleRecaptchaExpired.bind(this)}
    onLoad={this.handleRecaptchaLoaded.bind(this)}
/>}

And handled like this:

e.preventDefault();
if (!this.isValid()) return false;
this.captchaRef.execute();

this.props.onSubmit(this.state.fieldValues);

setTimeout(() => this.setState({
    fieldValues: {
        ...this..resetFieldValues(),
    },
}));
Sawtaytoes commented 7 years ago

Looks like execute() isn't synchronous and what I really need to do is, when submitting the form, now listen in my onChange handler for the captcha value. Once that comes in, I can call the passed in props.onSubmit.

This calls in a few other questions. If it doesn't give back a value or is invalid, does it show reCATPCHA V2 or is that something I need to control manually? The functionality of the old and new captcha are completely different so I'd need some way to know which captcha is showing at what time. A better method would be seeing that Invisible reCAPTCHA failed, I'd hide it and show the V2 element I have hidden somewhere on the page.

dozoisch commented 7 years ago

@Sawtaytoes I unfortunately can't answer that as I'm not using an invisible captcha in my projects. I would refer to what the google doc says

Sawtaytoes commented 7 years ago

Since I was unable to find this in the docs, I had to do some testing.

When it fails, it has an overlay that shows on top of your site. It will ask the same questions in a modal about selecting a house or trees etc. It does not show the button again. Once you click the blue verify button, your onChange is called as normal; thus, this can work in the onChange handler no problem.

leopucci commented 3 years ago

I am having the same trouble. to execute is not synchronous. so It didn't set the value to be used. I am using the executeAsync because of this problem.

dozoisch commented 3 years ago

@leopucci this library is a wrapper above google's library to make it simple to include in react-projects. Unfortunately execute is always asynchronous and that is how Google made ReCAPTCHA so I can't change that

leopucci commented 3 years ago

@dozoisch ok I am learning how to play with that. THanks