Last active
May 31, 2024 17:48
-
-
Save sladg/1e22ffccc7f1b4ec65f08ec0d22bca95 to your computer and use it in GitHub Desktop.
No-dependency implementation of Google's Recaptcha Enterprise.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- | |
// inside _app.tsx | |
import Script from 'next/script'; | |
// inside custom App component. | |
<Script src="https://www.google.com/recaptcha/enterprise.js?render=explicit" /> | |
--> | |
import { useEffect, useState } from 'react'; | |
declare global { | |
interface Window { | |
grecaptcha: { | |
enterprise: any; | |
}; | |
} | |
} | |
interface Props { | |
loadOnMount: boolean; | |
elementId: string; | |
} | |
export const useRecaptcha = ({ loadOnMount, elementId }: Props) => { | |
const [isLoaded, setIsLoader] = useState(false); | |
const [isError, setIsError] = useState(false); | |
const [token, setToken] = useState<string | null>(null); | |
const successCallback = (key: string) => { | |
setToken(key); | |
}; | |
const expireCallback = () => { | |
setIsError(true); | |
}; | |
const errorCallback = () => { | |
setIsError(true); | |
}; | |
const reset = () => { | |
setToken(null); | |
setIsError(false); | |
window.grecaptcha?.enterprise.ready(() => { | |
window.grecaptcha?.enterprise.reset(); | |
}); | |
}; | |
useEffect(() => { | |
if (!loadOnMount) { | |
return; | |
} | |
window.grecaptcha?.enterprise.ready(() => { | |
setIsLoader(true); | |
}); | |
}, []); | |
useEffect(() => { | |
const checkExist = setInterval(() => { | |
const el = document.getElementById(elementId); | |
if (!el) { | |
return; | |
} | |
clearInterval(checkExist); | |
try { | |
window.grecaptcha?.enterprise.render(el, { | |
sitekey: '______PUT_YOUR_RECAPTCHA_KEY_OVER_HERE______', | |
theme: 'light', | |
callback: successCallback, | |
'expired-callback': expireCallback, | |
'error-callback': errorCallback, | |
}); | |
} catch (e) { | |
// eslint-disable-next-line no-console | |
console.warn(e); | |
} | |
}, 250); | |
}, [isLoaded]); | |
return { isVerified: !!token, isError, token, reset }; | |
}; | |
<!-- | |
// inside your component | |
import { useRecaptcha } from './useRecaptcha.ts' | |
const recaptchaElementId = 'g-recaptcha-el' | |
const Component = () => { | |
const { isVerified, token, reset } = useRecaptcha({ | |
elementId: recaptchaElementId, | |
loadOnMount: true, | |
}); | |
// ..... | |
const handleSubmit = () => { | |
// send token to server with rest of your form data | |
// after submit, call reset() | |
} | |
// ..... | |
return ( | |
<div> | |
<div id={recaptchaElementId} /> | |
<button onClick={handleSubmit} disabled={isVerified}>Submit</button> | |
</div> | |
) | |
} | |
--> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment