[Stimulus.js 1.0.1] Targets not found in time

Fixed: This bug was fixed by upgrading to 1.1.1, which introduces a check to ensure the document.readyState is either complete or interactive when Application.start() is called. If anyone else has this issue and they’re still lagging behind on Stimulus 1.0.x, upgrading is easy and, while not guaranteed to be 100% compatible, caused us no issues in our monolith of a project. Original post below:

My team has a large, monolith, legacy app that has been around since Rails 3. It’s huge - 300+ models, thousands of controllers, and who knows how many views. So upgrading things isn’t easy, especially when we’re adding new features to it regularly. As a result, we’re still on Stimulus 1.0.1 and Rails 5.2. We’re planning upgrades in the spring, but an upgrade of this size with our small team often takes weeks, so we have to budget for those changes.

We have been using Stimulus since it came out, and it has proven, time and time again, to remedy all the issues we had with Backbone. As we move forward, we’ve been slowly migrating hundreds of Backbone views and models over to Stimulus, and working with raw JS instead of jQuery or CoffeeScript. And it’s been a great experience.

However, we have been having issues over the last year, primarily with handling targets on initialize/connect. They’re present on the DOM, but, during initialization of the Stimulus controller, it appears as if Stimulus almost reacts too quickly, not waiting for the DOM to fully load, resulting in targets not being found.

We had an issue in production earlier today where our little Stimulus controller to configure Stripe Elements and assign them to form fields started failing with Error: Missing target element "stripe-elements.cardNumber". This isn’t the first time this started occurring on production out of the blue, though this time it has affected our income stream. It has been humming along just fine otherwise, and there have been no significant changes to our codebase to warrant this all-of-a-sudden failure.

Our temporary solution has been a little mixin (coffeescript) that waits on the document.readyState, but even that is starting to fail at this point.

I understand we are on a bit of an outdated platform, but we don’t know why this is happening, and we don’t know what we need to do to resolve the issue: targets not being available on initialize.

Does the Rails app render the stripe-elements.cardNumber from the backend or frontend (i.e. Stripe Javascript)?

<script src="https://js.stripe.com/v3/"></script>

It’s a text field that is rendered with the DOM. As a matter of fact, it’s the first child element in this controller. Yet, Stimulus can’t find it unless I add a Promise back to the document.readyState or add a timeout.

I will say we have narrowed it down mostly to Chrome 97, as it doesn’t seem to occur nearly as often on 96, Safari, or Firefox.

Sorry, I’m still not clear. Is the text field rendered with the HTML (Rails) or with the DOM (Javascript)?

Are you able to share an example project which reproduces the issue?

So we found out that Application.start() on 1.0.1 does no checking if the DOM is ready, whereas 1.1.0 introduced a fix that waits for the DOM to be in either interactive or complete state before working. We upgraded, have noticed no changes, and that seems to have fixed the issues. Huzzah!

Glad you figured it out