firebase / firebase/firebase-js-sdk

grecaptcha keeps a reference to my div in window.___grecaptcha_cfg.clients even after RecaptchaVerifier.clear()

Open
#8,023 0 comments 3 reactions 0 assignees View on GitHub
api: auth needs-attention question stack:NextJS
Dominant language
TypeScript
Stars
5.1k
Forks
1k
Avg merge
2d 21h
Merged PRs (30d)
37

Description

### Operating System

macOS 14.2 (23C64)

### Browser Version

Chrome 121.0.6167.160 (Official Build) (arm64)

### Firebase SDK Version

10.8.0

### Firebase SDK Product:

Auth

### Describe your project's tooling

Next.js 14

### Describe the problem

When reloading my components (because some state changed or a code change triggered hot reload) I clear the RedirectVerifier and the innerHtml of the container div. Then when I create a new RecaptchaVerifier, pass the same div as container and try to render it I get an `Error: reCAPTCHA has already been rendered in this element`.

Using the chrome devtools I found out that grecaptcha has a reference to my div in `window.___grecaptcha_cfg.clients` even after I use RecaptchaVerifier.clear(). So when I try to render the new RecaptchaVerifier using the same div it breaks even if it is empty and the previos ReaptchaVerifier no longer exists.

I can work around this by manually clearing that reference between rerenders or by using a new div so it's not the same reference but I think RecaptchaVerifier.clear() should take care of this.

### Steps and code to reproduce issue

### Steps
1. Have an empty div
2. Create a RecaptchaVerifier using the div created in step 1 as container
3. Render the RecaptchaVerifier (RecaptchaVerifier.render())
4. Clear the RecaptchaVerifier (RecaptchaVerifier.render())
5. Clear the container div (containerRef.innerHtml = '')
6. Repeat steps 2 to 4

### My Code

**Recaptcha container**
```typescript
export type RecaptchaProps = {
containerRef: React.Ref;
};

export const Recaptcha = ({ containerRef }: RecaptchaProps) => {
return

;
};
```

**RecaptchaVerifier**
```typescript
import { getAuth, RecaptchaVerifier } from 'firebase/auth';
import { useCallback, useEffect, useState } from 'react';

export const useRecaptcha = () => {
const [containerRef, setContainerRef] = useState(null);
const [verifier, setVerifier] = useState();

const createVerifier = useCallback((containerRef: HTMLDivElement | null) => {
let verifier: RecaptchaVerifier | undefined;

if (containerRef !== null) {
console.log(containerRef);
verifier = new RecaptchaVerifier(getAuth(), containerRef, {
size: 'invisible',
});
}

return verifier;
}, []);

const clear = useCallback(
(
verifier: RecaptchaVerifier | undefined,
containerRef: HTMLDivElement | null,
) => {
verifier?.clear();
if (containerRef !== null) {
containerRef.innerHTML = '';
}
},
[],
);

useEffect(() => {
const newVerifier = createVerifier(containerRef);
newVerifier?.render().then(
() => {
setVerifier(newVerifier);
},
(error) => console.log(error),
);

return () => clear(newVerifier, containerRef);
}, [createVerifier, containerRef, setVerifier, clear]);

return { verifier, containerRef: setContainerRef };
};
```

**Login Page**

```typescript
const LoginPage = () => {
const { verifier, containerRef } = useRecaptcha()
[...]
return (


[...]


);
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.