mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[FIX] component: correctly create a new node when previous is destroyed
Previously, when a component node had been created and destroyed, and the corresponding component was then recreated, the destroyed node was reused. This commit fixes that
This commit is contained in:
committed by
Aaron Bohy
parent
ced5d0f69f
commit
15e4c856da
@@ -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;
|
||||
|
||||
@@ -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(\`<div>child</div>\`);
|
||||
|
||||
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
|
||||
) {
|
||||
|
||||
@@ -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`<div>child</div>`;
|
||||
setup() {
|
||||
useLogLifecycle(steps)
|
||||
}
|
||||
}
|
||||
|
||||
class Parent extends Component {
|
||||
static template = xml`<Child t-if="state.hasChild"/>`;
|
||||
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);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user