diff --git a/src/component/component_node.ts b/src/component/component_node.ts
index ac673047..6c3ba1ac 100644
--- a/src/component/component_node.ts
+++ b/src/component/component_node.ts
@@ -21,9 +21,13 @@ export function component(
let node: any = ctx.children[key];
let isDynamic = typeof name !== "string";
- if (node && node.status < STATUS.MOUNTED) {
- node.destroy();
- node = undefined;
+ if (node) {
+ if (node.status < STATUS.MOUNTED) {
+ node.destroy();
+ node = undefined;
+ } else if (node.status === STATUS.DESTROYED) {
+ node = undefined;
+ }
}
if (isDynamic && node && node.component.constructor !== name) {
node = undefined;
diff --git a/tests/components/__snapshots__/lifecycle.test.ts.snap b/tests/components/__snapshots__/lifecycle.test.ts.snap
index 603e9c53..642ae2b0 100644
--- a/tests/components/__snapshots__/lifecycle.test.ts.snap
+++ b/tests/components/__snapshots__/lifecycle.test.ts.snap
@@ -425,6 +425,36 @@ exports[`lifecycle hooks mounted hook is called if mounted in DOM 1`] = `
}"
`;
+exports[`lifecycle hooks mounted hook is called on every mount, not just the first one 1`] = `
+"function anonymous(bdom, helpers
+) {
+ let { text, createBlock, list, multi, html, toggler, component } = bdom;
+ let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue } = helpers;
+
+ let block1 = createBlock(\`
child
\`);
+
+ return function template(ctx, node, key = \\"\\") {
+ return block1();
+ }
+}"
+`;
+
+exports[`lifecycle hooks mounted hook is called on every mount, not just the first one 2`] = `
+"function anonymous(bdom, helpers
+) {
+ let { text, createBlock, list, multi, html, toggler, component } = bdom;
+ let { withDefault, getTemplate, prepareList, withKey, zero, call, callSlot, capture, isBoundary, shallowEqual, setContextValue } = helpers;
+
+ return function template(ctx, node, key = \\"\\") {
+ let b2;
+ if (ctx['state'].hasChild) {
+ b2 = component(\`Child\`, {}, key + \`__1\`, node, ctx);
+ }
+ return multi([b2]);
+ }
+}"
+`;
+
exports[`lifecycle hooks mounted hook is called on subcomponents, in proper order 1`] = `
"function anonymous(bdom, helpers
) {
diff --git a/tests/components/lifecycle.test.ts b/tests/components/lifecycle.test.ts
index f570caf8..1be37813 100644
--- a/tests/components/lifecycle.test.ts
+++ b/tests/components/lifecycle.test.ts
@@ -1064,4 +1064,54 @@ describe("lifecycle hooks", () => {
"C:patched",
]);
});
+
+ test("mounted hook is called on every mount, not just the first one", async () => {
+ const steps: string[] = [];
+ class Child extends Component {
+ static template = xml`child
`;
+ setup() {
+ useLogLifecycle(steps)
+ }
+ }
+
+ class Parent extends Component {
+ static template = xml``;
+ static components = { Child };
+ state = useState({ hasChild: true });
+ setup() {
+ useLogLifecycle(steps);
+ }
+ }
+
+ const parent = await mount(Parent, fixture);
+
+ parent.state.hasChild = false;
+ await nextTick();
+
+ parent.state.hasChild = true;
+ await nextTick();
+ expect(steps).toEqual([
+ "Parent:setup",
+ "Parent:willStart",
+ "Parent:render",
+ "Child:setup",
+ "Child:willStart",
+ "Child:render",
+ "Child:mounted",
+ "Parent:mounted",
+ "Parent:render",
+ "Parent:willPatch",
+ "Child:willUnmount",
+ "Child:destroyed",
+ "Parent:patched",
+ "Parent:render",
+ "Child:setup",
+ "Child:willStart",
+ "Child:render",
+ "Parent:willPatch",
+ "Child:mounted",
+ "Parent:patched"
+ ]);
+ Object.freeze(steps);
+ });
});