Unexpected behavior: Vuex watcher triggering twice

After searching for two hours, I still can't figure out what I'm doing wrong. I'm hoping someone can assist me with my issue:

Essentially, the problem is quite simple. I have a reusable component for Recaptchas. The specific element causing trouble is a textfield within a popup dialog for "forgot password" (above the login form).

The basic approach to handling multiple captchas on the same page is as follows:

  • I have a Vuex field for each potential captcha, initialized to null.
  • Upon clicking a form submit button, a mutation is triggered that sets the captcha field to 0.
  • I've set up watchers in the recaptcha component to listen for changes, and if the value equals 0, start evaluating the captcha.
  • Upon validation, invoking another mutation saves the result to Vuex. A separate watcher then checks for newVal and submits the data.

In theory, this should work seamlessly. I believe it has worked before, but after some recent modifications, it's behaving erratically.

To be precise: upon clicking the button once, everything seems fine, except one particular watcher fires twice when it shouldn't at all.

if (!this.running) {
    this.running = true
    console.log('forgot watcher 2')
    this.$refs.recaptcha.execute()
}

Despite using the condition above, it doesn't function as expected. It appears to run simultaneously, which is confusing to me.

The console output demonstrates this dilemma:

submit
verify forgot captcha
0
forgot watcher 2
0
forgot watcher 2
verified
forgot captcha verified 03AOLTBLTP...............
forgot watcher
verified
forgot watcher

Here is a simplified sequence of events:

  • Click on login.vue
  • Mutation sets the value to 0
  • Watcher in recaptcha.vue detects the change and starts evaluation (unfortunately, this trigger erroneously occurs twice)
  • If verified, verifyCaptcha() in recaptcha.vue stores the information in Vuex

Below are snippets from relevant files:

login.vue

<template>
  <v-form
    @submit.prevent="twoFaRequired ? sendTwoFa() : verifyLoginCaptcha()"
  >
    // ...
   <recaptcha />
    // ...
    <v-layout>
        <form>
           // ...
           <recaptcha />
           <v-btn
              color="primary"
              :loading="forgotLoading"
              :disabled="successful || forgotLoading || $v.$invalid"
              @click.native.stop.prevent="verifyForgotCaptcha"
            >Reset Password</v-btn>

//...
  methods: {
    verifyForgotCaptcha() {
      console.log('submit')
      this.$store.commit('user/VERIFY_FORGOT_CAPTCHA')
    },
//...
  watch: {
    forgotCaptcha(newVal, oldVal) {
      if (newVal) {
        console.log('forgot watcher')
        this.sendForgotEmail()
      }
    },
//...
    forgotCaptcha() {
      return this.$store.state.user.forgotCaptcha
    },

mutations.js

//...
  VERIFY_FORGOT_CAPTCHA(state) {
    console.log('verify forgot captcha')
    state.forgotCaptcha = 0
  },
  FORGOT_CAPTCHA_VERIFIED(state, payload) {
    console.log('forgot captcha verified', payload)
    state.forgotCaptcha = payload
  },
//...

recaptcha.vue

<template>
  <div class="d-flex justify-center">
    <vue-recaptcha
      ref="recaptcha"
      :sitekey=siteKey
      :loadRecaptchaScript="true"
      size="invisible"
      @verify="verifyCaptcha">
    </vue-recaptcha>
  </div>
</template>

<script>
  import VueRecaptcha from 'vue-recaptcha'
  import { mapGetters } from 'vuex'

  export default {
    data: () => ({
      running: false,
      usage: '',
      siteKey: 'xxxxxxx'
    }),
    components: { VueRecaptcha },
    computed: {
      ...mapGetters([
        'user'
      ]),
    //...
      isForgotCaptcha() {
        return this.$store.getters['user/forgotCaptcha']
      }
    },
    methods: {
      verifyCaptcha(response) {
        console.log('verified')
    //...
          if (this.usage === 'forgot')        this.$store.commit('user/FORGOT_CAPTCHA_VERIFIED', response)
        this.usage = ''
        this.$refs.recaptcha.reset()
      }
    },
    watch: {
    //...
      isForgotCaptcha(newVal) {
        if (newVal === 0) {
          console.log('forgot watcher 2')
          this.usage = 'forgot'
          this.$refs.recaptcha.execute()
        }
      },
    }
  };
</script>

If additional information or code is required, please don't hesitate to ask. I appreciate any insight into where I might be going wrong. Thank you!

Answer №1

Within the login.vue file, there are two occurrences of <recaptcha>. Each instance operates independently with its own set of watchers and computed property, isForgotCaptcha.

Any changes to user/forgotCaptcha will affect the isForgotCaptcha property in both components, triggering their respective watchers.

Modifying this.running will only impact one of the recaptcha components, leaving the other unaffected by the change.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What exactly is this issue? TypeError: Unable to retrieve property '0' from undefined

Encountering an issue while attempting to implement user authentication using mongodb and express. The error triggers every time the submit button is clicked on the website. This presents the first problem, followed by a second issue where the page continu ...

Similar to Angular ui-router 1.0.3, what is the equivalent function for reloadOn

After updating to UI-router v1.0.3 from v0.3.2, I noticed that the reloadOnSearch feature has been removed from the stateConfig. I'm having trouble finding the equivalent of reloadOnSearch in v1.0.3. It doesn't seem to be documented anywhere. A ...

Modifying selections within a select box generated dynamically using JQuery

Looking for help on how to delegate to a static DOM element in my current situation. I need to create a dynamic select box .userDrop when .addNew is clicked, and then have the user select an option from #secDrop, triggering a change event that calls the da ...

What is the reason for the function to return 'undefined' when the variable already holds the accurate result?

I have created a function that aims to calculate the digital root of a given number. Despite my efforts, I am encountering an issue where this function consistently returns undefined, even though the variable does hold the correct result. Can you help me ...

What is the best approach to conceal elements from the main template in Meteor using a template event?

I have a main template along with two others that are displayed using Iron routing: <template name="main"> <div id="templateMain" name="templateMain"> <a href="nfnoscar">The Legend of NFN Oscar</a> <br/> <a h ...

Dividing a string starting from the first appearance of a specific character

I need assistance with parsing multiple lines of text found in log files following this specific format: topic, the message part, contains occasional commas. Is there a method to separate the string starting from the first comma so that I can store the t ...

Encasing a series of AJAX calls in a function: Implementing JavaScript and JQuery

I am facing an issue with a chain of two AJAX requests within a forEach() loop, where the second request relies on the response of the first. I have tried to wrap this code block in a function for reusability, but it seems to stop working. As a beginner in ...

Implementing multiple filters with jQuery

Make a Selection `<select class="form-control" id="technology"> <option name="sort" value="2g" id="2g"gt;2G</option> <option name="sort" value="3g" id="3g"&g ...

Tips for shortening block text on your website with a link at the end

I'm currently working on implementing a truncating block of text with ellipses that can expand and collapse using a button in a React project. Individually, I've been able to truncate the text correctly with ellipses, and my coworker has position ...

Error: The 'browser' field in the NPM configuration is missing a valid alias setting

When running the following command: node .\node_modules\webpack\bin\webpack.js --config scripts/webpack.config.js --display-error-details An error is generated with the following details. Currently, I am testing the script and my ...

"Error occurred: Unable to execute bgColor as a function" on HTML select onchange event

I am having an issue with my HTML switch that has an onchange tag triggering the JavaScript function bgColor with the argument this. However, every time I attempt to use this, I receive an error message: Uncaught TypeError: bgColor is not a function. Can a ...

``What is the best way to access Vue i18n from a non-Vue class?

I have been utilizing the vue-i18n plugin for my Vue.js application. Everything has been working fine so far, except for one issue: how can I access the translations from a class that is not directly connected to Vue? Here is an example of a simple class ...

Retrieve the value from an object using a dot notation in its title

Currently, I am experimenting with creating a Facebook chatbot. To communicate with Facebook, I need to verify that I own the URL provided to Facebook in the Webhooks panel. I have set up an express route that appears as follows: app.get('/api/verif ...

What is the best way to prevent event bubbling in this particular code snippet?

$('#div1').on('click', '#otherDiv1', function(event){ //Show popup $('#popupDiv').bPopup({ modalClose: false, follow: [false, false], closeClass: 'close ...

What are some popular SCSS modules used in Nuxt.js development?

I have a common.scss file that I want to use across multiple components: .section { background-color: #f2f2f2; padding: 20px; ... } To include this file in my components, I currently import it like so: <template> <div :class="$style. ...

Get a section of a website using JavaScript

My website has a large amount of data that causes it to load slowly. Within this site, there is a table displaying all the information. I am looking for a way to allow users to download the content of the table without reloading the entire page and proces ...

Execute the extension exclusively within iframes

I'm developing a browser extension and I need certain parts of the code to only execute within iframes. Currently, all the code in my extension.js file is executed on both regular web pages and iframes. How can I identify whether the code is running w ...

Ways to display the values stored in localStorage in distinct div elements based on certain conditions

https://i.sstatic.net/BG3qd.png In my recent project, I have created a feature where users can input specific values through input fields and have them stored directly in localStorage. These values represent different tasks, such as Task: Work Description ...

Strange JSON.parse quirk observed in Node.js when dealing with double backslashes

My coworker encountered an issue while trying to parse a JSON string from another system, leading to unexpected behavior. To illustrate the problem, I have provided a simple code snippet below: // This code is designed for node versions 8 and above con ...

React context fails to refresh

I created a simple project that utilizes Context to store the page title, but I am experiencing an issue where the component is not being re-rendered after setting it. Main files: Context.js import React from 'react' const Context = React.cre ...