Next.js中显式渲染Google reCAPTCHA Enterprise组件报错问题
解决Next.js中reCAPTCHA Enterprise手动渲染的报错问题
问题核心
你遇到的报错本质是显式渲染模式下的脚本参数配置错误,以及Next.js环境下对reCAPTCHA加载时机的处理不当。错误提示里的api.js是reCAPTCHA旧版的脚本名,Enterprise版报错时会沿用这个提示文本,并非实际加载了旧脚本。
正确的手动渲染配置步骤
1. 修正脚本加载与初始化逻辑
显式渲染时,需确保全局回调在脚本加载前挂载,并用ready方法保证API完全初始化:
const key = "你的站点密钥"; const captchaRef = useRef<HTMLDivElement>(null); useEffect(() => { // 先挂载全局回调,确保脚本加载后能触发 (window as any).onloadCallback = () => { (window as any).grecaptcha.enterprise.ready(() => { if (captchaRef.current) { // 渲染reCAPTCHA到指定容器,可设置size隐藏徽章 (window as any).grecaptcha.enterprise.render(captchaRef.current, { sitekey: key, size: "invisible" // 完全隐藏徽章,需遵守合规声明要求 }); } }); }; // 加载Enterprise版脚本,显式渲染模式 const script = document.createElement('script'); script.src = `https://www.google.com/recaptcha/enterprise.js?onload=onloadCallback&render=explicit`; script.async = true; script.defer = true; document.body.appendChild(script); // 组件卸载时清理脚本与全局回调,避免重复加载冲突 return () => { document.body.removeChild(script); delete (window as any).onloadCallback; }; }, [key]);
2. 修正表单提交时的令牌获取逻辑
显式渲染后,调用execute需传入渲染后的容器或widget ID,而非直接传站点密钥:
const onSubmit: SubmitHandler<OrderFormInput> = async (data) => { try { // 等待API就绪 await new Promise(resolve => (window as any).grecaptcha.enterprise.ready(resolve)); // 通过容器ref获取验证令牌 const token = await (window as any).grecaptcha.enterprise.execute(captchaRef.current, { action: "place_order" }); data.recaptchaToken = token; // 调用后端验证接口 } catch (error) { console.error("reCAPTCHA令牌获取失败:", error); } };
3. 添加渲染容器到表单
在表单中手动放置reCAPTCHA的渲染节点:
<form onSubmit={handleSubmit(onSubmit)}> {/* 其他表单字段 */} <div ref={captchaRef}></div> <button type="submit">提交</button> </form>
关键注意事项
- 避免重复加载:Next.js客户端组件路由切换时可能重复渲染,必须在
useEffect返回函数中清理脚本和全局回调。 - 合规性要求:如果设置
size: "invisible"隐藏徽章,需在页面底部添加版权声明:<div style={{ fontSize: "12px", textAlign: "center", marginTop: "10px" }}> 本网站受Google reCAPTCHA保护,适用隐私政策和服务条款。 </div> - 密钥验证:确保使用GCP控制台创建的reCAPTCHA Enterprise专属密钥,且已将你的域名添加到密钥允许列表。
内容的提问来源于stack exchange,提问作者djk96
相关产品推荐
相关产品推荐

