From 14d3eb83ebc8aed10c5e1b4b260b5ff618f1fbbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Fri, 5 Apr 2019 16:30:35 +0200 Subject: [PATCH] imp: add willPatch hook --- src/component.ts | 18 ++++++++++++++---- tests/component.test.ts | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/component.ts b/src/component.ts index 10ae0d5d..cfa4b7e8 100644 --- a/src/component.ts +++ b/src/component.ts @@ -149,6 +149,14 @@ export class Component< */ mounted() {} + /** + * The willPatch hook is called just before the DOM patching process starts. + * It is not called on the initial render. This is useful to get some + * information which are in the DOM. For example, the current position of the + * scrollbar + */ + willPatch() {} + /** * This hook is called whenever a component did actually update its props, * state or env. @@ -340,10 +348,12 @@ export class Component< _patch(vnode) { this.__widget__.renderPromise = null; - this.__widget__.vnode = patch( - this.__widget__.vnode || document.createElement(vnode.sel!), - vnode - ); + if (this.__widget__.vnode) { + this.willPatch(); + this.__widget__.vnode = patch(this.__widget__.vnode, vnode); + } else { + this.__widget__.vnode = patch(document.createElement(vnode.sel!), vnode); + } } async _start(): Promise { this.__widget__.renderProps = this.props; diff --git a/tests/component.test.ts b/tests/component.test.ts index f5d9997a..a3865496 100644 --- a/tests/component.test.ts +++ b/tests/component.test.ts @@ -498,6 +498,45 @@ describe("lifecycle hooks", () => { await widget.updateState({ flag: false }); expect(destroyed).toBe(true); }); + + test("willPatch/updated hook", async () => { + const steps: string[] = []; + class ParentWidget extends Widget { + inlineTemplate = ` +
+ +
`; + widgets = { child: ChildWidget }; + state = { n: 1 }; + willPatch() { + steps.push("parent:willPatch"); + } + componentDidUpdate() { + steps.push("parent:updated"); + } + } + + class ChildWidget extends Widget { + willPatch() { + steps.push("child:willPatch"); + } + componentDidUpdate() { + steps.push("child:updated"); + } + } + const widget = new ParentWidget(env); + await widget.mount(fixture); + expect(steps).toEqual([]); + await widget.updateState({ n: 2 }); + + // Not sure about this order. If you disagree, feel free to open an issue... + expect(steps).toEqual([ + "child:willPatch", + "child:updated", + "parent:willPatch", + "parent:updated" + ]); + }); }); describe("destroy method", () => {