diff --git a/addons/web/static/src/core/dialog/dialog_container.js b/addons/web/static/src/core/dialog/dialog_container.js
index 564051f1487..daf0f96cc99 100644
--- a/addons/web/static/src/core/dialog/dialog_container.js
+++ b/addons/web/static/src/core/dialog/dialog_container.js
@@ -7,6 +7,9 @@ class ErrorHandler extends Component {
this.props.callback();
throw error;
}
+ shouldUpdate() {
+ return false;
+ }
}
ErrorHandler.template = tags.xml``;
diff --git a/addons/web/static/src/core/notifications/notification.js b/addons/web/static/src/core/notifications/notification.js
index 8da5dac114f..64cc6919e7c 100644
--- a/addons/web/static/src/core/notifications/notification.js
+++ b/addons/web/static/src/core/notifications/notification.js
@@ -9,6 +9,10 @@ export class Notification extends Component {
}
}
+ shouldUpdate() {
+ return false;
+ }
+
get className() {
let className;
switch (this.props.type) {
diff --git a/addons/web/static/src/core/popover/popover_container.js b/addons/web/static/src/core/popover/popover_container.js
index 2cfc2389bac..92a0ae68bc6 100644
--- a/addons/web/static/src/core/popover/popover_container.js
+++ b/addons/web/static/src/core/popover/popover_container.js
@@ -19,6 +19,11 @@ class PopoverController extends Component {
willUnmount() {
this.targetObserver.disconnect();
}
+
+ shouldUpdate() {
+ return false;
+ }
+
get popoverProps() {
return {
target: this.target,
diff --git a/addons/web/static/src/core/utils/components.js b/addons/web/static/src/core/utils/components.js
new file mode 100644
index 00000000000..eb86323c1cf
--- /dev/null
+++ b/addons/web/static/src/core/utils/components.js
@@ -0,0 +1,15 @@
+/** @odoo-module **/
+
+const { Component, tags } = owl;
+
+export function makeNonUpdatableComponent(Comp) {
+ class NoUpdate extends Component {
+ shouldUpdate() {
+ return false;
+ }
+ }
+ NoUpdate.template = tags.xml``;
+ NoUpdate.components = { Comp };
+
+ return NoUpdate;
+}
diff --git a/addons/web/static/src/webclient/webclient.js b/addons/web/static/src/webclient/webclient.js
index 038d78b846e..5a43cf9ff33 100644
--- a/addons/web/static/src/webclient/webclient.js
+++ b/addons/web/static/src/webclient/webclient.js
@@ -6,6 +6,7 @@ import { useBus } from "../core/bus_hook";
import { ActionContainer } from "./actions/action_container";
import { NavBar } from "./navbar/navbar";
import { useEffect } from "@web/core/effect_hook";
+import { makeNonUpdatableComponent } from "../core/utils/components";
const { Component, hooks } = owl;
const { useExternalListener } = hooks;
@@ -19,7 +20,11 @@ export class WebClient extends Component {
this.router = useService("router");
this.user = useService("user");
useService("legacy_service_provider");
- this.Components = mainComponentRegistry.getEntries();
+ this.Components = mainComponentRegistry.getEntries().map(([name, elem]) => {
+ const { Component, props } = elem;
+ const NonUpdatableComp = makeNonUpdatableComponent(Component);
+ return [name, { Component: NonUpdatableComp, props }];
+ });
this.title.setParts({ zopenerp: "Odoo" }); // zopenerp is easy to grep
useBus(this.env.bus, "ROUTE_CHANGE", this.loadRouterState);
useBus(this.env.bus, "ACTION_MANAGER:UI-UPDATED", (mode) => {
diff --git a/addons/web/static/tests/core/utils/component_tests.js b/addons/web/static/tests/core/utils/component_tests.js
new file mode 100644
index 00000000000..0c90101c44b
--- /dev/null
+++ b/addons/web/static/tests/core/utils/component_tests.js
@@ -0,0 +1,34 @@
+/** @odoo-module **/
+
+import { makeNonUpdatableComponent } from "@web/core/utils/components";
+import { makeTestEnv } from "../../helpers/mock_env";
+import { getFixture } from "../../helpers/utils";
+
+const { Component, mount } = owl;
+
+QUnit.module("utils", () => {
+ QUnit.module("components");
+
+ QUnit.test("makeNonUpdatableComponent", async function (assert) {
+ class Child extends Component {
+ mounted() {
+ assert.step("mounted");
+ }
+ willUpdateProps() {
+ assert.step("willupdateprops");
+ }
+ }
+ Child.template = owl.tags.xml`
hey
`;
+ class Parent extends Component {}
+ Parent.template = owl.tags.xml`
`;
+ Parent.components = { Child1: Child, Child2: makeNonUpdatableComponent(Child) };
+
+ const target = getFixture();
+ const parent = await mount(Parent, { env: makeTestEnv(), target });
+ assert.verifySteps(["mounted", "mounted"]);
+
+ await parent.render();
+ assert.verifySteps(["willupdateprops"]);
+ parent.destroy();
+ });
+});