Skip to content

Instantly share code, notes, and snippets.

@sladg
Last active May 31, 2024 17:48
Show Gist options
  • Save sladg/1e22ffccc7f1b4ec65f08ec0d22bca95 to your computer and use it in GitHub Desktop.
Save sladg/1e22ffccc7f1b4ec65f08ec0d22bca95 to your computer and use it in GitHub Desktop.
No-dependency implementation of Google's Recaptcha Enterprise.
<!--
// 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