react-grecaptcha-v3
Version:
Google Recaptcha V3 for React.js based application. Keep website performance high while prioritizing security.
85 lines (84 loc) • 3.11 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import { createContext, useCallback, useEffect, useMemo, useRef, } from 'react';
import subscribeEvent from './subscribeEvent';
import unsubscribeEvent from './unsubscribeEvent';
import useHandleNextInQueue from './useHandleNextInQueue';
import useQueueRef from './useQueueRef';
import { getScriptSrc, maybeInjectScript, maybeRemoveScript } from './utils';
export const Context = createContext(null);
export const defaultScriptId = 'rusted_labs_react_recaptcha_v3';
const ReCaptchaProvider = ({ siteKey, children, scriptProps = {}, useRecaptchaNet = false, enterprise = false, injectionDelay = null, }) => {
const injectCallbackRef = useRef(null);
const queueRef = useQueueRef();
const handleNextInQueue = useHandleNextInQueue(siteKey, queueRef);
useEffect(() => {
subscribeEvent(handleNextInQueue);
return () => {
unsubscribeEvent(handleNextInQueue);
};
}, [handleNextInQueue]);
useEffect(() => {
const reCaptchaScriptId = scriptProps.id || defaultScriptId;
if (null === siteKey) {
maybeRemoveScript(reCaptchaScriptId);
}
else {
const inject = () => {
maybeInjectScript({
src: getScriptSrc({
enterprise,
useRecaptchaNet,
siteKey,
}),
appendTo: scriptProps.appendTo ?? 'head',
id: reCaptchaScriptId,
async: scriptProps.async ?? true,
defer: scriptProps.defer ?? true,
nonce: scriptProps.nonce,
});
};
injectCallbackRef.current = inject;
if (injectionDelay === null) {
inject();
}
else {
const timeout = setTimeout(inject, injectionDelay);
return () => {
injectCallbackRef.current = null;
maybeRemoveScript(reCaptchaScriptId);
clearTimeout(timeout);
};
}
}
return () => {
maybeRemoveScript(reCaptchaScriptId);
};
}, [
enterprise,
handleNextInQueue,
injectionDelay,
scriptProps.appendTo,
scriptProps.async,
scriptProps.defer,
scriptProps.id,
scriptProps.nonce,
siteKey,
useRecaptchaNet,
]);
const executeRecaptcha = useCallback(async (action) => {
return new Promise((resolve, reject) => {
queueRef.current.push({
action,
onComplete: resolve,
onError: reject,
});
handleNextInQueue();
});
}, [handleNextInQueue, queueRef]);
const contextValue = useMemo(() => ({
executeRecaptcha,
injectScript: injectCallbackRef,
}), [executeRecaptcha]);
return _jsx(Context.Provider, { value: contextValue, children: children });
};
export default ReCaptchaProvider;