Skip to main content

Overview

useGoogleReCaptcha is a React hook that provides access to the reCAPTCHA context. It returns the executeRecaptcha function and container information, allowing you to manually execute reCAPTCHA and get tokens programmatically. Source: src/use-google-recaptcha.tsx:4

Import

import { useGoogleReCaptcha } from 'react-google-recaptcha-v3';

Signature

const useGoogleReCaptcha = (): IGoogleReCaptchaConsumerProps

Return Value

Returns an object with the following properties:
executeRecaptcha
((action?: string) => Promise<string>) | undefined
Function to execute reCAPTCHA and get a token. Returns undefined until reCAPTCHA is fully loaded.Parameters:
  • action (optional): String describing the action being performed (e.g., "login", "submit")
Returns:
  • Promise<string>: Resolves to the reCAPTCHA token
Throws:
  • Error if called before reCAPTCHA is loaded
container
string | HTMLElement | undefined
The container element used for explicit rendering, if configured in the provider.

Usage Examples

Basic Usage

import { useGoogleReCaptcha } from 'react-google-recaptcha-v3';

function MyComponent() {
  const { executeRecaptcha } = useGoogleReCaptcha();

  const handleSubmit = async () => {
    if (!executeRecaptcha) {
      console.log('Execute recaptcha not yet available');
      return;
    }

    const token = await executeRecaptcha('submit_form');
    // Send token to your backend
    console.log('Token:', token);
  };

  return <button onClick={handleSubmit}>Submit</button>;
}

Form Submission

import { useGoogleReCaptcha } from 'react-google-recaptcha-v3';
import { useState } from 'react';

function ContactForm() {
  const { executeRecaptcha } = useGoogleReCaptcha();
  const [formData, setFormData] = useState({ name: '', email: '' });

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();

    if (!executeRecaptcha) {
      console.error('reCAPTCHA not ready');
      return;
    }

    try {
      // Get reCAPTCHA token
      const token = await executeRecaptcha('contact_form');

      // Submit form with token
      const response = await fetch('/api/contact', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          ...formData,
          recaptchaToken: token
        })
      });

      if (response.ok) {
        console.log('Form submitted successfully');
      }
    } catch (error) {
      console.error('Error submitting form:', error);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={formData.name}
        onChange={(e) => setFormData({ ...formData, name: e.target.value })}
        placeholder="Name"
      />
      <input
        type="email"
        value={formData.email}
        onChange={(e) => setFormData({ ...formData, email: e.target.value })}
        placeholder="Email"
      />
      <button type="submit">Submit</button>
    </form>
  );
}

Multiple Actions

import { useGoogleReCaptcha } from 'react-google-recaptcha-v3';

function Dashboard() {
  const { executeRecaptcha } = useGoogleReCaptcha();

  const handleLogin = async () => {
    if (!executeRecaptcha) return;
    const token = await executeRecaptcha('login');
    // Process login with token
  };

  const handleDelete = async () => {
    if (!executeRecaptcha) return;
    const token = await executeRecaptcha('delete_item');
    // Process deletion with token
  };

  const handleUpdate = async () => {
    if (!executeRecaptcha) return;
    const token = await executeRecaptcha('update_profile');
    // Process update with token
  };

  return (
    <div>
      <button onClick={handleLogin}>Login</button>
      <button onClick={handleDelete}>Delete</button>
      <button onClick={handleUpdate}>Update Profile</button>
    </div>
  );
}

With Loading State

import { useGoogleReCaptcha } from 'react-google-recaptcha-v3';
import { useState } from 'react';

function SecureButton() {
  const { executeRecaptcha } = useGoogleReCaptcha();
  const [loading, setLoading] = useState(false);

  const handleClick = async () => {
    if (!executeRecaptcha) {
      alert('reCAPTCHA not ready. Please try again.');
      return;
    }

    setLoading(true);
    try {
      const token = await executeRecaptcha('button_click');
      
      // Verify token on backend
      const response = await fetch('/api/verify', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ token })
      });

      const data = await response.json();
      console.log('Verification result:', data);
    } catch (error) {
      console.error('Error:', error);
    } finally {
      setLoading(false);
    }
  };

  return (
    <button onClick={handleClick} disabled={loading || !executeRecaptcha}>
      {loading ? 'Processing...' : 'Submit'}
    </button>
  );
}

Custom Hook Wrapper

import { useGoogleReCaptcha } from 'react-google-recaptcha-v3';
import { useCallback } from 'react';

// Create a custom hook that wraps executeRecaptcha
function useRecaptchaVerify() {
  const { executeRecaptcha } = useGoogleReCaptcha();

  const verify = useCallback(
    async (action: string) => {
      if (!executeRecaptcha) {
        throw new Error('reCAPTCHA not initialized');
      }

      const token = await executeRecaptcha(action);
      
      // Verify token on your backend
      const response = await fetch('/api/verify-recaptcha', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ token, action })
      });

      if (!response.ok) {
        throw new Error('reCAPTCHA verification failed');
      }

      return response.json();
    },
    [executeRecaptcha]
  );

  return { verify, isReady: !!executeRecaptcha };
}

// Usage
function MyComponent() {
  const { verify, isReady } = useRecaptchaVerify();

  const handleAction = async () => {
    try {
      const result = await verify('my_action');
      console.log('Verified:', result);
    } catch (error) {
      console.error('Verification error:', error);
    }
  };

  return (
    <button onClick={handleAction} disabled={!isReady}>
      Protected Action
    </button>
  );
}

Error Handling

import { useGoogleReCaptcha } from 'react-google-recaptcha-v3';
import { useState } from 'react';

function SecureForm() {
  const { executeRecaptcha } = useGoogleReCaptcha();
  const [error, setError] = useState<string | null>(null);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    setError(null);

    if (!executeRecaptcha) {
      setError('reCAPTCHA is not ready yet. Please wait and try again.');
      return;
    }

    try {
      const token = await executeRecaptcha('form_submit');
      
      const response = await fetch('/api/submit', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ token })
      });

      if (!response.ok) {
        throw new Error('Submission failed');
      }

      console.log('Success!');
    } catch (err) {
      setError(
        err instanceof Error ? err.message : 'An unexpected error occurred'
      );
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      {error && <div className="error">{error}</div>}
      <button type="submit" disabled={!executeRecaptcha}>
        {executeRecaptcha ? 'Submit' : 'Loading reCAPTCHA...'}
      </button>
    </form>
  );
}

Important Notes

Check for Availability

Always check if executeRecaptcha is defined before calling it:
if (!executeRecaptcha) {
  // reCAPTCHA not ready yet
  return;
}
The function is undefined until the reCAPTCHA script loads and initializes.

Provider Required

This hook must be used within a component wrapped by GoogleReCaptchaProvider:
import { GoogleReCaptchaProvider } from 'react-google-recaptcha-v3';

function App() {
  return (
    <GoogleReCaptchaProvider reCaptchaKey="YOUR_SITE_KEY">
      <ComponentUsingHook />
    </GoogleReCaptchaProvider>
  );
}

Action Names

Action names help you analyze user behavior in the reCAPTCHA admin console. Use descriptive names:
  • "login"
  • "signup"
  • "purchase"
  • "comment"
  • "vote"

TypeScript Interface

interface IGoogleReCaptchaConsumerProps {
  executeRecaptcha?: (action?: string) => Promise<string>;
  container?: string | HTMLElement;
}
See TypeScript Interfaces for complete type definitions.

Comparison with GoogleReCaptcha Component

FeatureuseGoogleReCaptcha HookGoogleReCaptcha Component
ExecutionManual controlAutomatic on mount/changes
FlexibilityHigh - call anytimeLimited to lifecycle
Use caseUser actions, complex flowsSimple auto-verification
Code styleImperativeDeclarative
Use the hook when:
  • You need manual control over execution timing
  • You want to execute on button clicks or user actions
  • You need to handle complex validation flows
  • You’re using functional components
Use the component when:
  • You want automatic execution on mount
  • Token should refresh based on prop changes
  • You prefer declarative patterns

Build docs developers (and LLMs) love