-
Notifications
You must be signed in to change notification settings - Fork 792
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
Component Lifecycle Methods are not called in the correct order #1261
Comments
Added PR for tests: #1266 |
I can confirm this issue. |
Also confirming this issue. |
We checked the current codebase and then tried to find a solution for the order. The current queue in the core.browser does not respect the need that a child component maybe needs data from a parent component. If the order should be correct it should maybe work like the dummy code below. @adamdbradley My colleague @DanielTWalther and me tested that topic in the last days and came to the result that it's maybe necessary to rewrite the code in the core.browser to respect the order like in the dummy code below. What do you think about the topic and do you have plans for the queue mechanism in the core.browser? <a-test class="hydrated">
<b-test class="hydrated">
<div class="mytest">
<c-test class="hydrated">
</c-test>
<d-test class="hydrated">
<e-test class="hydrated">
</e-test>
</d-test>
</div>
</b-test>
</a-test> const bodyEl = document.querySelectorAll('body > *');
const iterateBodyWillLoad = async function(bodyEl) {
for(const el of bodyEl) {
if(el.classList.contains('hydrate')) {
// exec viewWillLoad of component
// await for viewWillLoad function
console.log('willLoad: ' + el.nodeName)
}
if(el.children) {
// check for children and recursively iterate
iterateBodyWillLoad(el.children);
}
if(el.classList.contains('hydrate')) {
// exec render function
console.log('render: '+ el.nodeName);
}
}
}
iterateBodyWillLoad(bodyEl); |
Well my opinion is that it would be the best. I'm currently doing sth similar in some sense to overcome the issue: looping recursively over parent's children in parent componentDidLoad and calling forceUpdate() on every Stencil component found to have some hook in child where parent is for sure initialized. But this is not the nicest and more of a temp solution. If you are able to change it I would definitely appreciate |
Hey, I just found acceptable (for me) solution for my issue with Redux store not being available in slot components. assuming that the root component is 'known' to any other component I can do sth like: componentWillLoad() {
document.querySelector("my-root-component").componentOnReady().then(() => {
this.store.mapDispatchToProps(this, {
getResources
});
this.store.mapStateToProps(this, state => {
return {
loading: state.payload.loading,
resources: state.payload.resources,
totalNoOfResources: state.payload.totalNoOfResources,
}
});
});
} |
Thanks for sharing - that will work for me too 😄 You can use async/await to make it cleaner: async componentWillLoad() {
await document.querySelector("my-root-component").componentOnReady();
...
} |
It also affects if you try to maintain components hierarchy such as <my-b>
<my-b>
<my-a>
</my-a>
</my-b>
</my-b> When current output
expected
|
maybe this will help: |
I tried using this, but sometimes it just crashes the app and the componentOnReady() seems to never finish. |
@fanick-ber try with:
I also noticed that it breaks the app when root component was actually loaded before child. Did not analyze yet why but |
Funny thing is that its about the alphabetical order of component names:) You can check in that test repo that I linked |
Thanks, it's really tough to understand what's going on there. I nested many slots and occasionally the content of a slot is just flushed before the actual slot position. I haven't found any solution beside shadowing all components (which is a bit more work for shared styles). |
When passing a conditional value to a component that has a slot, it causes the inner to dismount. I'm pretty sure its because of this. For example, <some-component>{condition ? 'something' : 'something else'}</some-component> When the condition changes is causes the text to dismount from the component. Is this issue still on the radar for a fix? We can use the workaround but it's a bit of an issue having to add the workaround to every component in our component lib. Thank you! |
This issue still persists in one of our recent examples: This does not work in a consistent way. Fails every couple of times.
This does work in a consistent way:
Kinda annoying. Anyone has a workaround? |
Can confirm it's still there for 0.18.1 :/
(It works in the same way in 1.0.0 alpha-12., but I'm not sure if this issue was considered resolved with 1.0.0-x) |
So we ended up doing the following (based on some replies in this thread), but not sure if it will stay and work across all major browsers etc. >>> We did not test it yet :) In the component that fails, we added the following code in the componentWillLoad() lifecycle hook:
It's definitely a work-around and hopefully not needed in some future releases. |
I was thinking that your fix is gonna help with #1439 but unfortunately it didn't :/ It seems that these are two different issues. |
@ps011 we did not test this yet on IE11. |
@adamdbradley Is anybody working on the issue ? It makes stencil simply unusable... 😢 |
I'll be working on something tomorrow to see if we can fix it somehow in our code. Maybe it could be ported to the core later on. I'll keep you posted. |
I cloned https://github.com/jarrvis/stencil-component-lifecycle-test.git and made a few minor changes with the old version.. reproduced the issue, then realized it was using a much older version of stenciljs. I upgraded the version (see changes here: SgtPooki/stencil-component-lifecycle-test@67416a6) and the issue was not gone. Output is below:
|
@manucorporat I can confirm: Agree with @MonsieurMan that this bug makes Stencil One unusable for many people. Therefore sticking with |
Same here. I started using Redux, and things are now broken due to the non deterministic nature of the order in which life cycle events fire. 2 out of 3 times, a child component will try to access the store which has not yet been created by the root component. @kraftwer1 Good to know |
That worked a treat! I encapsulated it in a small helper class as to not have to repeat the root component name in each child component (I have a lot of them). Now I can do: async componentWillLoad() {
await ComponentHelper.rootComponentReady();
...
} ComponentHelper: export class ComponentHelper {
static rootComponentReady(){
return document.querySelector("my-root-component").componentOnReady();
}
} |
I can also confirm this issue. |
This issue is still present in v1.5.4. For:
The 'will load'/'did load' order is incorrect and dependent on browser. Any feedback on the status of this? It's a fundamental problem and putting me off adopting stencil.js. |
Looking at the code, I can see why the order of lifecycle events is not correct. Here's the sequence of events from registering components to initial updates:
The problem stems from the fact that I don't have enough knowledge of the codebase to know what to do about this but it looks pretty fundamental. I can only assume that the current tests pass by coincidence because the components are nested in alphabetical order. |
@robinsummerhill Maybe a PR with a failing test would be a good first step ? edit: Just saw that OP actually added one back then. edit: I'm embarassed to do that, but @adamdbradley, @manucorporat, @jthoms1 could you give us your thoughts on this issue. Are you not going through it ? Do you use workarounds ? Is it too hard to fix and help is needed ? Thanks for your response. 🙂 |
Just a bit more information after looking at the existing tests and writing a new karma test for this particular issue: The problem does not occur when the nesting is set up using the render method of each component. i.e. cmp-c renders cmp-b and cmp-b renders cmp-a. Existing tests (e.g. The problem only occurs when the nesting is set up using nested elements in HTML and when the components are not in alphabetical order i.e.
More worryingly, I wrote a karma test for this issue, which should fail with the current version of Stencil. It fails when run manually and observed in the browser but passes when run under karma in headless Chrome or Firefox. It appears that the order of lifecycle events is very sensitive to the environment under which the test is being run. When observed manually in the browser the order is non-deterministic and will alter with each refresh of the page. (By the way, the reason that this is such an important issue is for cases where child components need to discover parent components or vice versa for communication - think component libraries with nested tab controls, selects with options or children retrieving a state container from a distant ancestor) |
Looks like @manucorporat refactored the lifecycle code three days ago in |
@robinsummerhill thank you for taking a look, so you've tried it on 1.6.0-2 and its still broke? |
Yes - it is broken in 1.6.0-2. The issue is very specific and not covered by any of the existing tests. Nesting needs to be set up in HTML not in the render method of a parent component and the tag names need to be in non-alphabetical order. The cause of the problem is that The PR above fixes the issue by deferring firing |
import '@stencil/redux'; this fixed the issue for me magically ! |
Looks like it's solved now, thanks @robinsummerhill and everyone for helping to pinpoint the issue |
Stencil version:
I'm submitting a:
[x] bug report
[ ] feature request
[ ] support request => Please do not submit support requests here, use one of these channels: https://stencil-worldwide.herokuapp.com/ or https://forum.ionicframework.com/
Current behavior:
The lifecycle methods are not called in the correct order:
NOTE: I've changed CmpA (cmp-a) to CmpZ (cmp-z) which makes the bug appear more often
Fails in Chrome on Windows, Safari on macOS and iOS/iPhone, Chrome on Android.
IE11 and Edge has the correct hiarchy but childs are loaded reversed.
Expected behavior:
The lifecycle methods should be called in the same order on server and client.
Steps to reproduce:
Refresh the following page and compare the server, and client messages. They should be in the same order:
https://stencil-bug.firebaseapp.com/prerender-z/
Changing the prerender-test component "cmp-a" tag, to "cmp-z" makes the lifecycle methods to be called out of order. This is the original test:
https://stencil-bug.firebaseapp.com/prerender-a/
Related code:
PR for tests: #1266
Other information:
#1130
The text was updated successfully, but these errors were encountered: