diff --git a/src/component/fiber.ts b/src/component/fiber.ts
index a761cc48..e40ed43f 100644
--- a/src/component/fiber.ts
+++ b/src/component/fiber.ts
@@ -98,6 +98,7 @@ export class Fiber {
_reuseFiber(oldFiber: Fiber) {
oldFiber.cancel(); // cancel children fibers
oldFiber.isCompleted = false; // keep the root fiber alive
+ oldFiber.isRendered = false; // the fiber has to be re-rendered
if (oldFiber.child) {
// remove relation to children
oldFiber.child.parent = null;
diff --git a/tests/component/component.test.ts b/tests/component/component.test.ts
index 9cd94647..2b65b6df 100644
--- a/tests/component/component.test.ts
+++ b/tests/component/component.test.ts
@@ -3463,6 +3463,51 @@ describe("async rendering", () => {
expect(fixture.innerHTML).toBe("
2|5
");
});
+ test("concurrent renderings scenario 12", async () => {
+ // In this scenario, we have a parent component that will be re-rendered
+ // several times simultaneously:
+ // - once in a tick: it will create a new fiber, render it, but will have
+ // to wait for its child (blocking) to be completed
+ // - twice in the next tick: it will twice reuse the same fiber (as it is
+ // rendered but not completed yet)
+ const def = makeDeferred();
+
+ class Child extends Component {
+ static template = xml``;
+ willUpdateProps() {
+ return def;
+ }
+ }
+
+ class Parent extends Component {
+ static template = xml`
`;
+ static components = { Child };
+ state = useState({ val: 1 });
+ }
+ Parent.prototype.__render = jest.fn(Parent.prototype.__render);
+
+ const parent = new Parent();
+ await parent.mount(fixture);
+ expect(fixture.innerHTML).toBe("1
");
+ expect(Parent.prototype.__render).toHaveBeenCalledTimes(1);
+
+ parent.state.val = 2;
+ await nextTick();
+ expect(fixture.innerHTML).toBe("1
");
+ expect(Parent.prototype.__render).toHaveBeenCalledTimes(2);
+
+ parent.state.val = 3;
+ parent.state.val = 4;
+ await nextTick();
+ expect(fixture.innerHTML).toBe("1
");
+ expect(Parent.prototype.__render).toHaveBeenCalledTimes(3);
+
+ def.resolve();
+ await nextTick();
+ expect(fixture.innerHTML).toBe("4
");
+ expect(Parent.prototype.__render).toHaveBeenCalledTimes(3);
+ });
+
test("change state and call manually render: no unnecessary rendering", async () => {
class Widget extends Component {
static template = xml`
`;