-
Notifications
You must be signed in to change notification settings - Fork 814
fix(dist-custom-elements): make watchers fire immediately when element already defined #6381
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
Conversation
thanks @kristilw ! Can you run |
…lement is already defined customElements.whenDefined always returns the answer asynchronously. Making the check synchronous when possible resolves the issue fixes: 6373 BREAKING CHANGE: Watchers will fire earlier than before, but this is the expected behavior
Done 👍 |
@johnjenkins This change introduces a breaking behavior in how Previously, watchers only fired when a prop actually changed after the component had mounted. That meant lifecycle guarantees were respected — DOM refs existed, and methods like With this change, watchers now fire immediately on initial prop assignment, before componentDidLoad or even before refs are set. This breaks a fundamental expectation in Stencil’s lifecycle and will cause regressions across many components. For example, in Ionic we have patterns like:
Before:
After:
This essentially changes the semantics of watchers from "respond to prop changes" → to "also run eagerly at init time", which was never the contract before. This will:
Suggestion: This should be reconsidered or at least gated behind a flag/major version bump, since it’s a breaking change that alters Stencil’s watcher lifecycle in a way that existing code cannot safely adapt without regressions. |
@exorex fair enough! |
@johnjenkins done #6388 Thank you for your efforts. |
If postponing watchers until it has rendered is the desired behaviour, why not just move the "isWatchReady" flag check to the |
@kristilw I will initially roll-back this change, but I'd love for you to try moving In the mean-time, I think we're gonna try and run the whole browser-based test suite in the Stencil codebase to pass over both dist and dist-custom-elements outputs (atm they mainly run over dist with some exceptions) |
After doing a small test I can at least verify that a lazy loaded component does indeed fire the watchers before the first rendrer (even before componentWillLoad). I think moving the |
fascinating! @exorex does this code:
work without error in the edit @kristilw - I see what's happening, in the dist / lazy-loader the incoming, initial value is set (and retained) internally before the component is even loaded. It means when the actual component module is fetched / loaded there's no changes on the value so no watchers are called. |
@johnjenkins You’re absolutely right — thanks for catching that. I should have clarified earlier: this issue only happens in the |
In my test of the
The watched method is not triggered on the first instance of the component. On the second component the watch is triggered immediately, before Moving the Do you know why the |
After moving |
Absolutely none :D - my guess is, you are correct in your guess - a 'hack' to give it similarity to the lazy variant.
I'd assume the tests are wrong. The diagram seems pretty definitive. With all that being said, however - idk how best to proceed as people come to rely on 'broken' behaviour like this :| Any thoughts @exorex ? (i'm leaning toward 'fixing' as making changes inside componentWillLoad seems weird to me) |
customElements.whenDefined always returns the answer asynchronously. Making the check synchronous when possible resolves the issue
fixes: #6373
BREAKING CHANGE: Watchers will fire earlier than before, but this is the expected behavior
What is the current behavior?
GitHub Issue Number: #6373
What is the new behavior?
Fixes so that watched methods are triggering as expected when an element is already defined.
Documentation
Does this introduce a breaking change?
I do not think i adds a breaking change as to how it was before 3.36.0, so I belive that no migration is nessecary.
Testing
I had planned to add a unit test to this code but found it very difficult. Looking at the initialize-component.spec.tsx file didnt give me much confidence either. Instead I tested it in a private professional project with many many components and verified that the code reproduction of the error in the github issue (https://github.com/mamillastre/stencil-demo/tree/angular-issue) also now works as expected.
Other information