Skip to content

Commit

Permalink
fix(runtime): fix lifecycle state values (#2414)
Browse files Browse the repository at this point in the history
  • Loading branch information
manucorporat authored May 5, 2020
1 parent 6bec727 commit 8302fed
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 16 deletions.
88 changes: 87 additions & 1 deletion src/runtime/test/lifecycle-sync.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Component, Element, Host, Prop, Watch, h } from '@stencil/core';
import { Component, Element, Host, Method, Prop, Watch, h } from '@stencil/core';
import { newSpecPage } from '@stencil/core/testing';
import { expectExtend } from '../../testing/matchers';

describe('lifecycle sync', () => {
it('should fire connected/disconnected when removed', async () => {
Expand Down Expand Up @@ -264,4 +265,89 @@ describe('lifecycle sync', () => {
]);
});
});

it('all state is available on "will" lifecycles', async () => {
@Component({ tag: 'cmp-child' })
class CmpChild {

@Prop() width = 0;
@Prop() height = 0;

componentWillLoad() {
expect(this.width).toEqual(100);
expect(this.height).toEqual(100);
}

componentWillUpdate() {
expect(this.width).toEqual(this.height);
}

componentWillRender() {
expect(this.width).toEqual(this.height);
}

render() {
return (
<Host>
{this.width}x{this.height}
</Host>
);
}
}

@Component({ tag: 'cmp-root' })
class CmpRoot {
@Prop() value = 100;
@Prop() value2 = 100;

@Method()
next() {
this.value *= 2;
this.value2 *= 2;
}

componentWillLoad() {
expect(this.value).toEqual(this.value2);
}

componentWillUpdate() {
expect(this.value).toEqual(this.value2);
}

componentWillRender() {
expect(this.value).toEqual(this.value2);
}

render() {
return (
<cmp-child
width={this.value}
height={this.value}
/>
)
}
}

const { root, waitForChanges } = await newSpecPage({
components: [CmpChild, CmpRoot],
template: () => <cmp-root></cmp-root>,
});
expect(root).toEqualHtml(`
<cmp-root>
<cmp-child>
100x100
</cmp-child>
</cmp-root>
`);
await root.next();
await waitForChanges();
expect(root).toEqualHtml(`
<cmp-root>
<cmp-child>
200x200
</cmp-child>
</cmp-root>
`);
});

});
23 changes: 14 additions & 9 deletions src/runtime/update-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,19 @@ export const scheduleUpdate = (hostRef: d.HostRef, isInitialLoad: boolean) => {
hostRef.$flags$ |= HOST_FLAGS.needsRerender;
return;
}
attachToAncestor(hostRef, hostRef.$ancestorComponent$);

// there is no ancestorc omponent or the ancestor component
// has already fired off its lifecycle update then
// fire off the initial update
const dispatch = () => dispatchHooks(hostRef, isInitialLoad);
return BUILD.taskQueue ? writeTask(dispatch) : dispatch;
};

const dispatchHooks = (hostRef: d.HostRef, isInitialLoad: boolean) => {
const elm = hostRef.$hostElement$;
const endSchedule = createTime('scheduleUpdate', hostRef.$cmpMeta$.$tagName$);
const ancestorComponent = hostRef.$ancestorComponent$;
const instance = BUILD.lazyLoad ? hostRef.$lazyInstance$ : (elm as any);
const update = () => updateComponent(hostRef, instance, isInitialLoad);
attachToAncestor(hostRef, ancestorComponent);

let promise: Promise<void>;
if (isInitialLoad) {
Expand Down Expand Up @@ -56,12 +63,10 @@ export const scheduleUpdate = (hostRef: d.HostRef, isInitialLoad: boolean) => {
}

endSchedule();

// there is no ancestorc omponent or the ancestor component
// has already fired off its lifecycle update then
// fire off the initial update
return then(promise, BUILD.taskQueue ? () => writeTask(update) : update);
};
return then(promise, () => (
updateComponent(hostRef, instance, isInitialLoad)
));
}

const updateComponent = (hostRef: d.HostRef, instance: any, isInitialLoad: boolean) => {
// updateComponent
Expand Down
1 change: 1 addition & 0 deletions test/karma/test-app/lifecycle-update/cmp-a.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export class LifecycleUpdateA {
}

componentWillUpdate() {

const li = document.createElement('li');
li.innerHTML = `<span style="color:maroon">lifecycle-update-a</span> <span style="color:cyan">componentWillUpdate</span> ${this.values[this.values.length - 1]}`;
document.getElementById('output')!.appendChild(li);
Expand Down
14 changes: 8 additions & 6 deletions test/karma/test-app/lifecycle-update/karma.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ describe('lifecycle-update', function() {
loads = app.querySelectorAll('#output li');
expect(loads[0].textContent).toBe('lifecycle-update-a componentWillLoad');
expect(loads[1].textContent).toBe('lifecycle-update-a componentDidLoad');
expect(loads[2].textContent).toBe('lifecycle-update-a componentWillUpdate 1');
expect(loads[3].textContent).toBe('async add child components to lifecycle-update-a 1');


expect(loads[2].textContent).toBe('async add child components to lifecycle-update-a 1');
expect(loads[3].textContent).toBe('lifecycle-update-a componentWillUpdate 1');
expect(loads[4].textContent).toBe('lifecycle-update-b componentWillLoad 1');
expect(loads[5].textContent).toBe('lifecycle-update-c componentWillLoad 1');
expect(loads[6].textContent).toBe('lifecycle-update-c componentDidLoad 1');
Expand All @@ -39,15 +41,15 @@ describe('lifecycle-update', function() {
loads = app.querySelectorAll('#output li');
expect(loads[0].textContent).toBe('lifecycle-update-a componentWillLoad');
expect(loads[1].textContent).toBe('lifecycle-update-a componentDidLoad');
expect(loads[2].textContent).toBe('lifecycle-update-a componentWillUpdate 1');
expect(loads[3].textContent).toBe('async add child components to lifecycle-update-a 1');
expect(loads[2].textContent).toBe('async add child components to lifecycle-update-a 1');
expect(loads[3].textContent).toBe('lifecycle-update-a componentWillUpdate 1');
expect(loads[4].textContent).toBe('lifecycle-update-b componentWillLoad 1');
expect(loads[5].textContent).toBe('lifecycle-update-c componentWillLoad 1');
expect(loads[6].textContent).toBe('lifecycle-update-c componentDidLoad 1');
expect(loads[7].textContent).toBe('lifecycle-update-b componentDidLoad 1');
expect(loads[8].textContent).toBe('lifecycle-update-a componentDidUpdate 1');
expect(loads[9].textContent).toBe('lifecycle-update-a componentWillUpdate 2');
expect(loads[10].textContent).toBe('async add child components to lifecycle-update-a 2');
expect(loads[9].textContent).toBe('async add child components to lifecycle-update-a 2');
expect(loads[10].textContent).toBe('lifecycle-update-a componentWillUpdate 2');
expect(loads[11].textContent).toBe('lifecycle-update-b componentWillLoad 2');
expect(loads[12].textContent).toBe('lifecycle-update-c componentWillLoad 2');
expect(loads[13].textContent).toBe('lifecycle-update-c componentDidLoad 2');
Expand Down

0 comments on commit 8302fed

Please sign in to comment.