Reputation: 353
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.
Upvotes: 6
Views: 3360
Reputation: 6667
You can do this to prevent calling connect twice:
export default class extends Controller {
connect() {
if (document.documentElement.hasAttribute('data-turbo-preview')) {
return;
}
// ...this code will be called once
}
}
This if condition prevents execution of the code for the first connect
call when turbolinks/turbo restores page html from the cache.
Note: for turbolinks attribute is data-turbolinks-preview
and for turbo attribute is data-turbo-preview
Upvotes: 2
Reputation: 1038
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/
Upvotes: 9