t49tran / react-google-recaptcha-v3

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

Script reloads on provider rerender if `scriptProps` prop is present #109

Closed nmalyarsky closed 2 years ago

nmalyarsky commented 2 years ago

If the scriptProps prop is specified in a GoogleReCaptchaProvider, then a full cleanup/inject cycle will be initiated on each provider rerender, even if scriptProps object stays semantically the same. This is due to the nature of useEffect and object equality.

Issue is easily replicated using barebone Next.js app with routing and a custom App like this one:

import type { AppProps } from 'next/app'

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <GoogleReCaptchaProvider scriptProps={{ async: true }} reCaptchaKey="KEY">
      <Component {...pageProps} />
    </GoogleReCaptchaProvider>
  )
}

export default MyApp

Each route change rerenders GoogleReCaptchaProvider, { async: true } object fails equality check and script reloads.

This behavior can be avoided by using a state variable in a consumer code. I'm also ready to open a PR in case you are willing to fix the issue in a library itself.

johndanek commented 2 years ago

"This behavior can be avoided by using a state variable in a consumer code." Do you have an example of this? I've run into the same issue and am a bit confused as to how to stop this frequent reloading.

nmalyarsky commented 2 years ago

Sure, using example above:

import type { AppProps } from 'next/app'

function MyApp({ Component, pageProps }: AppProps) {
  const [scriptProps] = useState({ async: true })

  return (
    <GoogleReCaptchaProvider scriptProps={scriptProps} reCaptchaKey="KEY">
      <Component {...pageProps} />
    </GoogleReCaptchaProvider>
  )
}

export default MyApp
johndanek commented 2 years ago

@nmalyarsky Thank you!