Why is my Stimulus JS controller firing twice?

Viewed 1214

So, I have a Rails application with webpacker, vue, turbolinks and stimulus js installed.
The problem that I am having is that even though the controller is only imported once and even if I temporarily disable turbolinks the initialize() funcition along with the connect() one get called twice.
This only happens if I do a refresh (i.e. not when I visit the page for the first time, but only if I perform a page reload).
Strangely enough the disconnect() is only getting called once (when I do leave the page)

This sucks because I need to modify the DOM in the initialize, so I get elements added twice. Does someone have any clue to what's causing this, and / or a solution?

EDIT: application.js as requested

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")

import "stylesheets"
import "controllers"
import "components"

components/index.js

import Vue from 'vue/dist/vue.esm'
import BootstrapVue from 'bootstrap-vue'
import TurbolinksAdapter from 'vue-turbolinks'

Vue.use(BootstrapVue)
Vue.use(TurbolinksAdapter)

const components = {}
const context = require.context("components", true, /_component\.vue$/)
context.keys().forEach(filename => {
  const component_name = filename.replace(/^.*[\\\/]/, '').replace(/_component\.vue$/, '')
  const component = context(filename).default
  components[component_name] = component
})

document.addEventListener('turbolinks:load', () => {
  const app = new Vue({
    el: '#vueapp',
    mounted() {
      let input = document.querySelector('[autofocus]');
      if (input) {
        input.focus()
      }
    },
    components: { ...components }
  })
})

controllers/index.js

import { Application } from "stimulus"
import { definitionsFromContext } from "stimulus/webpack-helpers"

const application = Application.start()
const context = require.context("controllers", true, /_controller\.js$/)
application.load(definitionsFromContext(context))

in each and every file, if I console.log it gets logged only once...
only in the stimulus controller initialize or connect gets printed twice

this happens only when I reload the page, not when I first visit it.

1 Answers

This is probably due to Turbolinks. When navigating to a new page, Turbolinks first presents a cached version of the page (first stimulus connect) and afterwards replaces the body with the actual requested version of the page (second stimulus connect). See here for more details:

https://mrcodebot.com/turbolinks-calls-stimulus-connect-twice/

Related