0

I am very new to react/hooks and struggling hard to get Google recaptcha working properly.

This is how my app.js looks like:

import ConfirmationPage from './Pages/ConfirmationPage';

function App() {
  const [email, setEmail] = React.useState('');
  const captchaRef = useRef({});

  function someFunction() {
      //Uses captchaRef to do something
  }

  return (
    <ConfirmationPage email={email} setEmail={setEmail} captchaRef={captchaRef}></ConfirmationPage>
  );
}

And this is how my ConfirmationPage.js looks like:

import ReCAPTCHA from "react-google-recaptcha";
import { Grid, TextField, Divider } from '@material-ui/core';

export default function ConfirmationPage({email, setEmail, captchaRef}) {
  function onChange(value) {
    console.log("Captcha Verified");
  }

 function handleEmailBlur(email){        
        setEmail(email);
     }

  return (
    <> 
      <TextField
           required
           id="txt_summary_email"
           label={'Email'}
           defaultValue={email}
           className={classes.FulltextField}
           margin="normal"
           onBlur={event=>handleEmailBlur(event.target.value)}                              
          />
        <ReCAPTCHA
            ref ={captchaRef}
            sitekey={process.env.REACT_APP_CAPTCHAKEY}
            onChange={onChange}
         /> 
    </>
  );

The problem occurs when a user tries to enter email value into txt_summary_email TextField, Captcha re-renders itself and loses its validation status. In other words, validate Captcha by clicking the empty box and try to enter email into the text field, Captcha will lose the validation check.

This is happening because of setEmail(email) in handleEmailBlur function. If I comment out setEmail(email), Captcha does not re-render itself. It looks like setting state in app.js somehow triggers the captcha to re-load.

How can I prevent the captcha from being re-rendered when setState is triggered?

Thank you very much for your help!

A J
  • 53
  • 1
  • 11
  • 1
    Move local state for email text field inside your confirmation page component. Because when you update email, it will trigger the component to reload everytime. Other way round you can use React.Memo and React.useCallback for your setEmail function. But not sure it will help you. Nice solution will be to keep the email state inside comfirmationPage component – Mohit Jul 04 '20 at 05:48
  • @Mohit Thank you for your suggestions, Mohit. However, I need to access email value from App.js. Is there a way for the parent(App.js) to access its child's(ConfirmationPage.js) state? – A J Jul 04 '20 at 05:54
  • 1
    Yes there are multiple ways by which you can achieve that. First if you can keep it at common state level i.e. using Redux. But if you're not using Redux, then you can use forwardRef feature of react. https://reactjs.org/docs/forwarding-refs.html You can pass the ref to the child and then you can access the child state in parent using ref only. Once ref is attached then you can find ref.current.state which will provide you child state – Mohit Jul 04 '20 at 06:03
  • 1
    Yes you can try implementing this using forwardRef – Mohit Jul 04 '20 at 06:52
  • @Mohit, Thank you very much for your suggestions, it now works like magic! I had to tweak it a bit since I using hooks, but I would've wasted so much time without your help. Thank you again! – A J Jul 05 '20 at 06:16
  • @Mohit, basically pointed me to the right direction to get this done. Anyone who wonders what I did to make this work, please refer to https://stackoverflow.com/questions/54702565/how-to-access-childs-state-in-react-react-hooks – A J Jul 05 '20 at 06:23
  • 1
    Cheers!! Happy to help :) – Mohit Jul 06 '20 at 05:22

0 Answers0