Skip to content
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

Question about Stimulus' life cycle #768

Open
fritzmg opened this issue May 21, 2024 · 2 comments
Open

Question about Stimulus' life cycle #768

fritzmg opened this issue May 21, 2024 · 2 comments

Comments

@fritzmg
Copy link

fritzmg commented May 21, 2024

I have a question or may be a misconception about the life cycle of Stimulus controllers.

Let's say I have a simple controller that toggles a <body> class and stores that state in localStorage:

// foobar_controller.js
import { Controller } from '@hotwired/stimulus'

export default class extends Controller {
    toggle() {
        document.body.classList.toggle('foobar');
        localStorage.setItem('foobar', document.body.classList.contains('foobar'));
    }
}
<head>
    <script src="app.js" async></script>
</head>
<body><button type="button" data-controller="foobar" data-action="foobar#toggle">Toggle Class</button></body>

Now I also want to restore that body class state which is saved in localStorage. My initial though was to put that into the initialize() method:

import { Controller } from '@hotwired/stimulus'

export default class extends Controller {
    initialize() {
        if ('true' === localStorage.getItem('foobar')) {
            document.body.classList.add('foobar');
        }
    }

    
}

My expectation was that (once app.js is loaded and cached by the browser) this would be immediately executed as soon as the node the controller is registered on is started to be processed by the browser.

However, in actuality it kind of looks like all Stimulus controllers are only initialized once the whole page finished loading - i.e. it almost looks like everything is only processed on DOMContentLoaded. I assumed that stimulus controllers would be initialized as soon as possible via Mutation observers. Thus in this case the body class is added too late for my use case.

Or another example would be the click action for a menu button - the event listener only seems to be added once the whole DOM was loaded, meaning that on a large page the menu button (which is at the very top of the page typically) does nothing for quite some time.

Was my expectation wrong? Or is there something wrong with my setup. In my case I use webpack - together with hotwired/stimulus-webpack-helpers. The app.js looks like this for example:

import { Application } from '@hotwired/stimulus'
import { definitionsFromContext } from '@hotwired/stimulus-webpack-helpers'
import './css/app.scss';

// Start Stimulus application
const application = Application.start()
const context = require.context('./controllers', true, /\.js$/)
application.load(definitionsFromContext(context));
application.debug = process.env.NODE_ENV === 'development';
@ildarkayumov
Copy link

However, in actuality it kind of looks like all Stimulus controllers are only initialized once the whole page finished loading - i.e. it almost looks like everything is only processed on DOMContentLoaded

you are right

please check this PR https://github.com/hotwired/stimulus/pull/131/files#diff-f3d6212b4c84ebef921d7f88435f66b4637ec31917aa74d48849e15773d6670cR25

so Application#start is async function that awaits for DOMContentLoaded runs all observers only after

@fritzmg
Copy link
Author

fritzmg commented Jun 3, 2024

I see, thank you for clarifying.

Ideally though it would be great if Stimulus controllers and actions are initialised as soon as possible - otherwise it might take a long time until event listeners are registered for example, e.g. when the DOM is large (see menu button example above).

However, I realise this might be tricky to implement, especially if controllers depend on each other.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants