Bug: False positive warning with nested roots: Attempted to synchronously unmount a root while React was already rendering.

This issue has been created since 2022-11-14.

we get a warning on (legitimate?) use case, if there is a manually added react root inside another parent root
(for example for part of Backbone view that is inserted into parent react component)
on unmount we can see that child root is in commit context, so we cant unmount it

React version: 18.2

Steps To Reproduce

  1. have nested react roots, child is manually added/removed on parent mount/unmount
  2. unmount parent root

I have 2 way bindings for backbone.marionette and react

  • reactToMarionette
  • useMarionetteInReact hook
    when root/parent component gets rendered/destroyed React gives this warning
Warning: Attempted to synchronously unmount a root while React was already rendering.
React cannot finish unmounting the root until the current render has completed,
which may lead to a race condition.

I am looking for ways to fix this warning

I think ReactChild node is somehow marked as toBeRendered at the app render, even though I would expect that app.root would not know about nested/inserted MView react root

Link to code example: https://codesandbox.io/s/my-test-adapters-forked-tdbgdb

problematic code
import { View } from "backbone.marionette";
import React, { useCallback, useRef, useState } from "react";

import { createRoot } from "react-dom/client";

export function App() {
  // create a reason to render inner component
  const [isVisible, setVisible] = useState(true);
  const toggle = useCallback(() => setVisible((i) => !i), []);

  console.log("render app", isVisible);
  return (
    <>
      <button onClick={toggle}>{`toggle: ${isVisible}`}</button>
      {isVisible ? <SomeComponent /> : null}
    </>
  );
}

// component that children are controlled from outside (by marionette)
const SomeComponent = () => {
  console.log("render SomeComponent");
  const ref = useMarionetteInReact();
  return <div ref={ref} className="stable-react-div"></div>;
};

// hook, for rendering marionette view
const useMarionetteInReact = () => {
  const viewRef = useRef(null);

  const divRef = useCallback((el) => {
    if (el === null) {
      console.log("MView destroy in useCallback", viewRef.current);
      viewRef.current && viewRef.current.destroy();
    } else {
      console.log("created MView");
      const MView = new reactToMarionette({
        className: "reactToMarionette",
        template: false,
        component: <ReactChild />
      });
      viewRef.current = MView;
      MView.render();
      el.appendChild(MView.el);
    }
  }, []);

  return divRef;
};

class reactToMarionette extends View {
  constructor(options) {
    super(options);
    this.component = options.component;
    this.el.textContent = "I am Marionette";

    console.log("create root", this.el);
    this.divEl = document.createElement("div");
    this.divEl.classList.add("portal-root");
    this.root = createRoot(this.divEl);
    this.el.append(this.divEl);
  }

  render() {
    console.log("MView render");
    this.root.render(this.component);
  }

  onBeforeDestroy() {
    console.log("onBeforeDestroy", this.root);
    if (this.root) {
      // setTimeout(() => this.root.unmount());
      this.root.unmount();
    }
  }
}

const ReactChild = () => {
  console.log("render ReactChild");
  return <div> Hello, I am react child </div>;
};

The current behavior

warning is displayed

The expected behavior

no warning ?

More Details About Repo
Owner Name facebook
Repo Name react
Full Name facebook/react
Language JavaScript
Created Date 2013-05-24
Updated Date 2022-12-10
Star Count 198882
Watcher Count 6638
Fork Count 41302
Issue Count 1120

YOU MAY BE INTERESTED

Issue Title Created Date Comment Count Updated Date
The experience on complex questions with semantic nuance 0 2022-05-10 2022-11-24
Question about freezing LM parameter problem 0 2022-03-19 2022-11-24
Wrong emoji names: U+1F38F(🎏) 1 2021-02-17 2022-11-01
zip not sending first try 9 2022-05-26 2022-08-14
Installation for Windows OS? 2 2021-04-01 2022-11-03
Seeking instructions for building the projects 3 2021-10-26 2022-11-17
Add default record values to all tracks 1 2021-06-01 2022-09-10
Save the segmented objects to a different folder 0 2022-02-01 2022-11-20
I noticed that custom level function is just available for PC. I want to play my custom levels with android divices (tablets and mobiles). 1 2021-05-12 2022-11-07
error: evaluation aborted with the following error message: 'Package not available: ox-chameleon' 3 2021-10-26 2022-10-07
documentation: flake + emacs-overlay 6 2021-11-06 2022-10-16
Asic miner Setup 2 2021-11-25 2021-12-31
Getting the following error upon executing `make install` 5 2021-09-05 2022-11-21
🐞 - Postfix is not aligned with placeholder in TuiInputNumber 0 2022-06-28 2022-10-20
Don't crash when Android API key is not set 5 2021-11-19 2022-09-30
run demo.py for video output error 6 2021-12-09 2022-12-02
Bug report: '*' in unordered list was resolved to Italic mark 1 2021-12-02 2022-11-12
[Defect] Not Able to Go to Build Details Sometimes 1 2022-09-16 2022-11-27
Mac Catalyst Snap & Drag Issue 6 2021-04-08 2022-12-01
Fatal performance degradation due to precompilation or inference bugs 8 2021-06-22 2022-11-13
Inline Translation Function 2 2022-04-21 2022-12-04
How to render back to markdown? 3 2020-06-26 2022-11-23
Just launched UWP windows are missing from the Windows 10 window switcher 21 2021-11-03 2022-12-09
LookupError: Could not match any of the results on YouTube for 2 2022-07-10 2022-10-30
Document that https://github.com/sbt/sbt/issues/3934 needs to be worked around 0 2021-12-03 2022-04-01
Replace Goto Symbol on @ character as well 2 2022-11-02 2022-12-02
pgxpool is auto scalable? 3 2021-09-01 2022-12-10
Invalid data: only uncompressed keys are supported. 2 2021-04-02 2022-11-29
alias doesnt work as expected in vue-cli 1 2021-09-01 2022-10-25
Glassy - everything option, make everything look like the Nautilus as an option 0 2022-09-01 2022-11-28
Completely remove `map_binary` 0 2021-10-15 2022-11-06
Possibility to add retry ability 5 2021-11-02 2022-11-28
Consolidate Error responses 1 2021-12-01 2022-10-12
Add command line arguement to change default configuration folder from the regular "C:\Users\<username>\AppData\Roaming\PrusaSlicer" 2 2022-06-19 2022-11-07
The Virtcontainers HypervisorConfig codes added three new fields, the API keeped old version 0 2021-09-14 2022-11-17
Using State with long_callback 0 2021-08-11 2022-10-23
Avoid recommending deprecated practice of calling setup.py directly 3 2021-11-01 2022-12-09
fix(engine): correct OR task query JSON conversion 1 2021-08-23 2022-11-30
Installation in a middle of operation stops with blank screen 0 2021-12-01 2022-11-17
train loss curve is realy weird 1 2021-04-06 2022-11-21
Redesign Follow-up 3 2021-12-31 2022-01-14
[Bug]: PDP - 404 - Error handling 0 2021-11-29 2022-11-11
Parallel train on folds for CV 0 2021-10-03 2022-12-08
Authoryzacja Device Flow 11 2021-12-06 2022-10-24
Remove support for JSON-based arrow flight tickets 0 2022-04-12 2022-10-01
Add tests for interaction between WebTransport and the GOAWAY frame 0 2022-10-06 2022-12-01
Implement the CLOSE_WEBTRANSPORT_SESSION capsule and add the H3_WEBTRANSPORT_SESSION_GONE error code 0 2022-10-06 2022-12-01
Replace references to echoserver with supported image from all documentation 34 2021-04-15 2022-12-01
Enhancement: Support parsing plain HTML 9 2018-07-15 2022-10-26
Allow customizing Jwt claims and headers 2 2020-12-07 2022-11-27