Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I change and commit the state inside settimeout function in Vuex?

form(@submit.prevent="onSubmit")
   input(type="text" v-model="platform" placeholder="Add platform name...")
   input(type="submit" value="Submit" class="button" @click="clicked = true")
   button(type="button" value="Cancel" class="btn" @click="cancelNew") Cancel      
      h3(v-if="clicked")  Thank you for adding a new platform 
         span {{ countdown }} 

This is my template and when the user submits the form, I want to count down from 3 using setTimeout function and submit after 3 seconds.

If I have it this way, it works;

data() {
  return {
    countdown: 3,
    platform: ""
  }
},
methods: {
  countDownTimer() {
    setTimeout(() => {
      this.countdown -= 1
      this.countDownTimer()
    }, 1000)
  },
  onSubmit() {
    let newplatform = {
      name: this.platform
    }
    this.addPlatform(newplatform)
    this.platform = ' ' 
    this.countDownTimer()
  }
}

However I have 3 more forms and I didn't want to repeat the code. So I wanted to put countdown in the store,

countDownTimer({commit}) {
  setTimeout(() => {
    countdown = state.countdown
    countdown -= 1
    commit('COUNTDOWN', countdown)
    this.countDownTimer()
  }, 1000)
}

and mutate it like

COUNTDOWN(state, countdown) {
  state.countdown = countdown
}

This doesn't work and I am not sure If I am able to change the state, commit the changes inside of settimeout function? Is there a better way I can implement this?

like image 767
bdemirka Avatar asked Jan 09 '21 18:01

bdemirka


People also ask

What is commit in VUEX?

In Vuex, mutations are synchronous transactions: store. commit('increment') // any state change that the "increment" mutation may cause // should be done at this moment. To handle asynchronous operations, let's introduce Actions.

How many times setTimeout executed?

As specified in the HTML standard, browsers will enforce a minimum timeout of 4 milliseconds once a nested call to setTimeout has been scheduled 5 times.

Does setTimeout run once?

The setTimeout function runs only once per call, meaning that after the execution of the callback function completes, setTimeout has finished its job. Note: For a countdown that restarts automatically, executing the callback function several times with a timed break between each execution, please see setInterval().


Video Answer


1 Answers

The issues:

  1. The recursive setTimeout isn't stopped.
  2. The countdown timer isn't reset.
  3. Use setInterval (and clearInterval) instead of the recursive setTimeout.
  4. For async logic including setTimeout, use an action rather than a mutation.
  5. Include state from the context object (where you get commit), or it will be undefined.

Try this:

actions: {
  countDownTimer({ state, commit, dispatch }) {  // state, commit, dispatch
    commit('RESET');
    const interval = setInterval(() => {         // Use `setInterval` and store it
      commit('COUNTDOWN');
      if (state.countdown === 0) {
        clearInterval(interval);                 // Clear the interval
        dispatch('updateDatabase');              // Call another action
      }
    }, 1000)
  }
}
mutations: {
  RESET(state) {
    state.countdown = 3;
  },
  COUNTDOWN(state) {
    state.countdown--;
  }
}
like image 174
Dan Avatar answered Oct 14 '22 17:10

Dan