diff --git a/CHANGELOG.md b/CHANGELOG.md
index cf79c233..314835ed 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -81,7 +81,6 @@ All changes are documented here in no particular order.
- improved performance
- much simpler code
- new App class to encapsulate a root Owl component (with the config for that application) ([doc](doc/reference/app.md))
-- new `Memo` component
- new `useEffect` hook ([doc](doc/reference/hooks.md#useeffect))
- breaking: `Context` is removed ([details](#15-context-is-removed))
- breaking: `env` is now totally empty ([details](#16-env-is-now-totally-empty))
@@ -249,35 +248,12 @@ Rationale: `shouldUpdate` is a dangerous method to use, that may cause a lot of
issues. Vue does not have such a mechanism (see https://github.com/vuejs/vue/issues/4255),
because the reactivity system in Vue is smart enough to only rerender the minimal
subset of components that is subscribed to a piece of state. Now, Owl 2 features
-a much more powerful reactivity system.
+a much more powerful reactivity system, so the same rationale applies: in a way,
+it's like each Owl 2 component has a `shouldUpdate` method that precisely tracks
+every value used by the component.
-Migration code: remove the `shouldUpdate` methods. Then, maybe the following
-ideas may help:
-
-- try to organize the state/architecture to minimize the number of state updates
-- take advantage of the finer reactivity system. For example, if we have a list
- of items, with a component for each item, we can write this:
-
- ```js
- class Item extends Component {
- setup() {
- this.item = useState(this.props.item); // and only use this, not props.item
- }
- }
- ```
- Doing so will make it that each `Item` component will register itself as an
- observer of its own item, and will be the only component being rerendered when
- its item object is updated.
-- use the `Memo` component to wrap some piece of template. `Memo` memoize its
- content, and only update itself if its props are different (shallow comparison):
-
- ```xml
-
-
-
-
-
- ```
+Migration code: remove the `shouldUpdate` methods, and it should work as well
+as before.
### 9. component.el is removed
diff --git a/src/index.ts b/src/index.ts
index b901704c..ca67b8d4 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -42,7 +42,6 @@ export { App, mount } from "./app/app";
export { Component } from "./component/component";
export { useComponent, useState } from "./component/component_node";
export { status } from "./component/status";
-export { Memo } from "./memo";
export { xml } from "./app/template_set";
export { reactive, markRaw, toRaw } from "./reactivity";
export { useEffect, useEnv, useExternalListener, useRef, useChildSubEnv, useSubEnv } from "./hooks";
diff --git a/src/memo.ts b/src/memo.ts
deleted file mode 100644
index b8787bd6..00000000
--- a/src/memo.ts
+++ /dev/null
@@ -1,47 +0,0 @@
-import { Component } from "./component/component";
-import type { ComponentNode } from "./component/component_node";
-import { xml } from "./app/template_set";
-import { Fiber } from "./component/fibers";
-
-export class Memo extends Component {
- static template = xml``;
-
- constructor(props: any, env: any, node: ComponentNode) {
- super(props, env, node);
-
- // prevent patching process conditionally
- let applyPatch = false;
- const patchFn = node.patch;
- node.patch = () => {
- if (applyPatch) {
- patchFn.call(node);
- applyPatch = false;
- }
- };
-
- // check props change, and render/apply patch if it changed
- let prevProps = props;
- const updateAndRender = node.updateAndRender;
- node.updateAndRender = function (props: any, parentFiber: Fiber) {
- const shouldUpdate = !shallowEqual(prevProps, props);
- if (shouldUpdate) {
- prevProps = props;
- updateAndRender.call(node, props, parentFiber);
- applyPatch = true;
- }
- return Promise.resolve();
- };
- }
-}
-
-/**
- * we assume that each object have the same set of keys
- */
-function shallowEqual(p1: any, p2: any): boolean {
- for (let k in p1) {
- if (k !== "slots" && p1[k] !== p2[k]) {
- return false;
- }
- }
- return true;
-}
diff --git a/tests/misc/__snapshots__/memo.test.ts.snap b/tests/misc/__snapshots__/memo.test.ts.snap
deleted file mode 100644
index 6501fb70..00000000
--- a/tests/misc/__snapshots__/memo.test.ts.snap
+++ /dev/null
@@ -1,71 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Memo if no prop change, prevent renderings from above 1`] = `
-"function anonymous(bdom, helpers
-) {
- let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
- let { markRaw } = helpers;
-
- function slot1(ctx, node, key = \\"\\") {
- let b6 = text(ctx['state'].a);
- let b7 = text(ctx['state'].b);
- let b8 = text(ctx['state'].c);
- return multi([b6, b7, b8]);
- }
-
- return function template(ctx, node, key = \\"\\") {
- let b2 = text(ctx['state'].a);
- let b3 = text(ctx['state'].b);
- let b4 = text(ctx['state'].c);
- let b9 = component(\`Memo\`, {a: ctx['state'].a, b: ctx['state'].b,slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx);
- return multi([b2, b3, b4, b9]);
- }
-}"
-`;
-
-exports[`Memo if no props, prevent renderings from above 1`] = `
-"function anonymous(bdom, helpers
-) {
- let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
- let { markRaw } = helpers;
-
- function slot1(ctx, node, key = \\"\\") {
- return component(\`Child\`, {value: ctx['state'].value}, key + \`__2\`, node, ctx);
- }
-
- return function template(ctx, node, key = \\"\\") {
- let b2 = component(\`Child\`, {value: ctx['state'].value}, key + \`__1\`, node, ctx);
- let b4 = component(\`Memo\`, {slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__3\`, node, ctx);
- return multi([b2, b4]);
- }
-}"
-`;
-
-exports[`Memo if no props, prevent renderings from above 2`] = `
-"function anonymous(bdom, helpers
-) {
- let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
-
- return function template(ctx, node, key = \\"\\") {
- return text(ctx['props'].value);
- }
-}"
-`;
-
-exports[`Memo if no props, prevent renderings from above (work with simple html) 1`] = `
-"function anonymous(bdom, helpers
-) {
- let { text, createBlock, list, multi, html, toggler, component, comment } = bdom;
- let { markRaw } = helpers;
-
- function slot1(ctx, node, key = \\"\\") {
- return text(ctx['state'].value);
- }
-
- return function template(ctx, node, key = \\"\\") {
- let b2 = text(ctx['state'].value);
- let b4 = component(\`Memo\`, {slots: markRaw({'default': {__render: slot1, __ctx: ctx}})}, key + \`__1\`, node, ctx);
- return multi([b2, b4]);
- }
-}"
-`;
diff --git a/tests/misc/memo.test.ts b/tests/misc/memo.test.ts
deleted file mode 100644
index 2ae3a13a..00000000
--- a/tests/misc/memo.test.ts
+++ /dev/null
@@ -1,92 +0,0 @@
-import { Component, mount, useState, xml } from "../../src";
-import { Memo } from "../../src/";
-import { makeTestFixture, nextTick, snapshotEverything } from "../helpers";
-
-let fixture: HTMLElement;
-
-snapshotEverything();
-
-beforeEach(() => {
- fixture = makeTestFixture();
-});
-
-describe("Memo", () => {
- test("if no props, prevent renderings from above ", async () => {
- class Child extends Component {
- static template = xml``;
- }
- class Test extends Component {
- static template = xml`
-
-
-
- `;
-
- static components = { Memo, Child };
-
- state = useState({ value: 1 });
- }
-
- const component = await mount(Test, fixture);
-
- expect(fixture.innerHTML).toBe("11");
- component.state.value = 2;
- await nextTick();
- expect(fixture.innerHTML).toBe("21");
- });
-
- test("if no props, prevent renderings from above (work with simple html) ", async () => {
- class Test extends Component {
- static template = xml`
-
-
-
- `;
-
- static components = { Memo };
-
- state = useState({ value: 1 });
- }
-
- const component = await mount(Test, fixture);
-
- expect(fixture.innerHTML).toBe("11");
- component.state.value = 2;
- await nextTick();
- expect(fixture.innerHTML).toBe("21");
- });
-
- test("if no prop change, prevent renderings from above ", async () => {
- class Child extends Component {
- static template = xml``;
- }
-
- class Test extends Component {
- static template = xml`
-
-
-
-
-
-
-
- `;
-
- static components = { Memo, Child };
-
- state = useState({ a: "a", b: "b", c: "c" });
- }
-
- const component = await mount(Test, fixture);
-
- expect(fixture.innerHTML).toBe("abcabc");
-
- component.state.c = "C";
- await nextTick();
- expect(fixture.innerHTML).toBe("abCabc");
-
- component.state.a = "A";
- await nextTick();
- expect(fixture.innerHTML).toBe("AbCAbC");
- });
-});