-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ERROR Cannot start nuxt: Cannot read properties of undefined (reading 'options') 16:21:56 #123
Comments
I'm also getting this error, here is the stack trace in case it helps.
|
Oh, seems like nuxt3 isn't supported right now. Perhaps this is a good alternative in the meantime: abinnovision/vue-recaptcha-v3#609 |
You can use the following plugin snippet for Nuxt 3 support, same steps will work. if you need the recaptcha component just copy it from the repository to your nuxt components folder. Add recaptcha options to the runtime config in nuxt.config export default defineNuxtPlugin((nuxtApp) => {
const { grecaptcha } = useRuntimeConfig().public
nuxtApp.provide('recaptcha', new ReCaptcha(grecaptcha))
})
const API_URL = 'https://www.recaptcha.net/recaptcha/api.js'
// https://github.com/PierfrancescoSoffritti/light-event-bus.js/blob/master/src/EventBus.js
function EventBus() {
const subscriptions = {}
this.subscribe = function subscribeCallbackToEvent(eventType, callback) {
const id = Symbol('id')
if (!subscriptions[eventType]) subscriptions[eventType] = {}
subscriptions[eventType][id] = callback
return {
unsubscribe: function unsubscribe() {
delete subscriptions[eventType][id]
if (
Object.getOwnPropertySymbols(subscriptions[eventType]).length === 0
) {
delete subscriptions[eventType]
}
},
}
}
this.publish = function publishEventWithArgs(eventType, arg) {
if (!subscriptions[eventType]) return
Object.getOwnPropertySymbols(subscriptions[eventType]).forEach((key) =>
subscriptions[eventType][key](arg)
)
}
}
class ReCaptcha {
constructor({ hideBadge, language, mode, siteKey, version, size }) {
if (!siteKey) {
throw new Error('ReCaptcha error: No key provided')
}
if (!version) {
throw new Error('ReCaptcha error: No version provided')
}
this._elements = {}
this._grecaptcha = null
this._eventBus = null
this._ready = false
this.hideBadge = hideBadge
this.language = language
this.siteKey = siteKey
this.version = version
this.size = size
this.mode = mode
}
destroy() {
if (this._ready) {
this._ready = false
const { head } = document
const { style } = this._elements
const scripts = [...document.head.querySelectorAll('script')].filter(
(script) => script.src.includes('recaptcha')
)
if (scripts.length) {
scripts.forEach((script) => head.removeChild(script))
}
if (head.contains(style)) {
head.removeChild(style)
}
const badge = document.querySelector('.grecaptcha-badge')
if (badge) {
badge.remove()
}
}
}
async execute(action) {
try {
await this.init()
if ('grecaptcha' in window) {
return this._grecaptcha.execute(this.siteKey, { action })
}
} catch (error) {
throw new Error(`ReCaptcha error: Failed to execute ${error}`)
}
}
getResponse(widgetId) {
return new Promise((resolve, reject) => {
if ('grecaptcha' in window) {
if (this.size == 'invisible') {
this._grecaptcha.execute(widgetId)
window.recaptchaSuccessCallback = (token) => {
this._eventBus.publish('recaptcha-success', token)
resolve(token)
}
window.recaptchaErrorCallback = (error) => {
this._eventBus.publish('recaptcha-error', error)
reject(error)
}
} else {
const response = this._grecaptcha.getResponse(widgetId)
if (response) {
this._eventBus.publish('recaptcha-success', response)
resolve(response)
} else {
const errorMessage = 'Failed to execute'
this._eventBus.publish('recaptcha-error', errorMessage)
reject(errorMessage)
}
}
}
})
}
init() {
if (this._ready) {
// make sure caller waits until recaptcha get ready
return this._ready
}
this._eventBus = new EventBus()
this._elements = {
script: document.createElement('script'),
style: document.createElement('style'),
}
const { script, style } = this._elements
script.setAttribute('async', '')
script.setAttribute('defer', '')
const params = []
if (this.version === 3) {
params.push('render=' + this.siteKey)
}
if (this.language) {
params.push('hl=' + this.language)
}
let scriptUrl = API_URL
if (this.mode === 'enterprise') {
scriptUrl = scriptUrl.replace('api.js', 'enterprise.js')
params.push('render=' + this.siteKey)
}
script.setAttribute('src', scriptUrl + '?' + params.join('&'))
window.recaptchaSuccessCallback = (token) =>
this._eventBus.publish('recaptcha-success', token)
window.recaptchaExpiredCallback = () =>
this._eventBus.publish('recaptcha-expired')
window.recaptchaErrorCallback = () =>
this._eventBus.publish('recaptcha-error', 'Failed to execute')
this._ready = new Promise((resolve, reject) => {
script.addEventListener('load', () => {
if (this.version === 3 && this.hideBadge) {
style.innerHTML = '.grecaptcha-badge { display: none }'
document.head.appendChild(style)
} else if (this.version === 2 && this.hideBadge) {
// display: none DISABLES the spam checking!
// ref: https://stackoverflow.com/questions/44543157/how-to-hide-the-google-invisible-recaptcha-badge
style.innerHTML = '.grecaptcha-badge { visibility: hidden; }'
document.head.appendChild(style)
}
this._grecaptcha = window.grecaptcha.enterprise || window.grecaptcha
this._grecaptcha.ready(resolve)
})
script.addEventListener('error', () => {
document.head.removeChild(script)
reject('ReCaptcha error: Failed to load script')
this._ready = null
})
document.head.appendChild(script)
})
return this._ready
}
on(event, callback) {
return this._eventBus.subscribe(event, callback)
}
reset(widgetId) {
if (this.version === 2 || typeof widgetId !== 'undefined') {
this._grecaptcha.reset(widgetId)
}
}
render(reference, { sitekey, theme }) {
return this._grecaptcha.render(reference.$el || reference, {
sitekey,
theme,
})
}
} |
This sounds like an amazing solution, unfortunately it's missing some clarity and I haven't managed to make it work. |
1- add the snippet in new plugin file in the plugins folder |
For all the ones that need a little more help:
|
What is the exact options of the plugin? I added the below code in nuxt.config.ts file but I got the same error |
@efesezer Did you make sure to remove the package ( |
@efesezer I don't have enough info to debug this issue. I googled the error ( |
Thanks for your help. I managed to run the captcha module and saw the picture selection panel. However, I did not get the captha token. First I tried with execute method and it returned null
After that, I tried with getResponse method, nothing happened. I couldnt get the captcha token.
What should I do in order to get captcha token? |
@efesezer The site key should go in nuxt.config file, not the way you're passing it
|
@efesezer You need to define the |
What does the parameter suppose to be in execute method? You gave "login" in the example, but What is this value? Is it the button id or form id? |
@efesezer It does not matter. You can decide. They call it 'action name'. I think you can read it in the backend so you can identify what this token is meant to be used for. It does totally not affect the functionality, so providing 'foobarbaz' is also fine. |
@marcdix Thank you for your help. I have one issue left. I am using below code in order to get captcha token. However it returns null. All configurations are done correctly. Where am I doing wrong? Could you please help me on this issue?
|
@efesezer That's why I asked if you know how When you can't or don't want to use async / await, then you can chain with a function runStuff() {
useNuxtApp().$recaptcha.execute('login').then((token) => {
// the token is ONLY available in here, you can not
// log/use it "outside" of this function
console.log(token);
});
} |
I know the concept of async/await functions. I am calling the execute method with await option in an async function. However I still could not get the captcha token. async submit (e) {
e.preventDefault()
var reCaptcha = await useNuxtApp().$recaptcha.execute('checkCustomer')
console.log(reCaptcha)
// prints the value null
} I should get the captcha token immediately because I am using await keyword in async function. But it returns null |
🤔 Only thing I can now imagine is that your siteKey could be wrong(ly configured). Else it looks good. |
I used the snippet above For the configuration, I used the code below {
runtimeConfig: {
public: {
grecaptcha: {
hideBadge: true,
mode: "base",
siteKey: "MY VALID SITE KEY HERE",
version: 3,
language: "tr-TR"
},
},
},
} Are they wrong? What should I do add more apart from them? |
Yes, looks all fine - I'm using a very similar configuration. The only thing I can not check if all is right with your siteKey. So if you say you are 100% sure that the siteKey is right and must work, then I don't know what else you could try. You have the setup I have as well. |
Maybe this article could help us --> https://dev.to/elquimeras/integrate-recaptcha-v3-on-nuxt3-app-1gma |
Hi I follow your guide but when I try to get the token by running the execute method, I have this error: "ReCaptcha error: Failed to execute Error: Invalid site key or not loaded in api.js: XXX XXX is my site key and I am pretty sure it's valid since my current WordPress page is using it Here's my page:
My nuxt.config.ts:
My plugins/recaptcha.ts is exactly like yours |
ERROR Cannot start nuxt: Cannot read properties of undefined (reading 'options') 16:21:56
The text was updated successfully, but these errors were encountered: