Imperative Handle
Imperative Handle
Overview
Each provider exposes an imperative handle so you can programmatically control the widget (e.g. reset, execute) and access provider-specific methods like reading the current response.
The handle is fully typed per provider and the implementation differs between frameworks:
- React: Uses refs with
useRef
andforwardRef
- Qwik: Uses signals with
useSignal
and theonReady$
event - SolidJS: Uses a controller pattern with
createCaptchaController
- Vue: Uses template refs or the
useCaptcha
composable for reactive access - Svelte: Uses
bind:this
to access component methods directly
Usage
import { useRef } from "react";
import { ReCaptcha, type ReCaptchaHandle } from "@better-captcha/react/provider/recaptcha";
export default function Example() {
const recaptchaRef = useRef<ReCaptchaHandle>(null!);
return (
<>
<ReCaptcha sitekey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI" ref={recaptchaRef} />
<button onClick={() => recaptchaRef.current.execute()}>Execute</button>
<button onClick={() => recaptchaRef.current.reset()}>Reset</button>
<button onClick={() => console.log(recaptchaRef.current.getResponse())}>Log response</button>
</>
);
}
The handle is available as soon as the widget is rendered. Until then, a safe no-op handle is exposed to keep type-safety.
import { component$, useSignal } from "@builder.io/qwik";
import { useCaptchaController } from "@better-captcha/qwik";
import { ReCaptcha, type ReCaptchaHandle } from "@better-captcha/qwik/provider/recaptcha";
export default component$(() => {
const controller = useCaptchaController<ReCaptchaHandle>();
return (
<>
<ReCaptcha
sitekey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"
controller={controller}
/>
<button onClick$={() => controller.value?.execute()}>Execute</button>
<button onClick$={() => controller.value?.reset()}>Reset</button>
<button onClick$={() => console.log(controller.value?.getResponse())}>Log response</button>
</>
);
});
The handle is passed via the onReady$
event. Store it in a signal and use optional chaining when calling methods.
import { ReCaptcha, type ReCaptchaHandle, createCaptchaController } from "@better-captcha/solidjs/provider/recaptcha";
export default function Example() {
const controller = createCaptchaController<ReCaptchaHandle>();
return (
<>
<ReCaptcha sitekey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI" controller={controller} />
<button onClick={() => controller.handle()?.execute()}>Execute</button>
<button onClick={() => controller.handle()?.reset()}>Reset</button>
<button onClick={() => console.log(controller.handle()?.getResponse())}>Log response</button>
</>
);
}
The controller's handle()
function returns the handle once the widget is ready, or null
if not yet initialized. Always use optional chaining when calling methods.
<template>
<ReCaptcha
ref="recaptchaRef"
sitekey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"
@ready="onReady"
/>
<button @click="execute">Execute</button>
<button @click="reset">Reset</button>
<button @click="logResponse">Log response</button>
</template>
<script setup lang="ts">
import { useCaptcha } from "@better-captcha/vue";
import { ReCaptcha, type ReCaptchaHandle } from "@better-captcha/vue/provider/recaptcha";
const { captchaRef, handle, execute, reset } = useCaptcha<ReCaptchaHandle>();
const recaptchaRef = captchaRef;
const onReady = (readyHandle: ReCaptchaHandle) => {
console.log("Captcha ready", readyHandle);
};
const logResponse = () => {
console.log(handle.value?.getResponse());
};
</script>
useCaptcha()
keeps a stable handle reference and exposes helpers like execute
and reset
. You can also access the handle directly via ref="recaptchaRef"
.
<script lang="ts">
import ReCaptcha from "@better-captcha/svelte/provider/recaptcha";
import type { ReCaptchaHandle } from "@better-captcha/svelte/provider/recaptcha";
let captchaRef: ReCaptcha | undefined;
function onReady(handle: ReCaptchaHandle) {
console.log("Captcha ready", handle);
}
function execute() {
captchaRef?.execute();
}
function reset() {
captchaRef?.reset();
}
function logResponse() {
console.log(captchaRef?.getResponse());
}
</script>
<ReCaptcha
bind:this={captchaRef}
sitekey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"
onready={onReady}
/>
<button onclick={execute}>Execute</button>
<button onclick={reset}>Reset</button>
<button onclick={logResponse}>Log response</button>
Use bind:this
to get a reference to the component instance, then call methods directly on it. Always use optional chaining since the reference may be undefined.
Common Methods
All providers implement these methods on the handle:
Prop
Type
Provider-specific methods
Provider-specific methods (e.g. getState
) are documented on each provider page: