Skip to content

Commit

Permalink
SWC-7102 - Synchronously create a new root, asynchronously cleanup th…
Browse files Browse the repository at this point in the history
…e old root
  • Loading branch information
nickgros committed Oct 17, 2024
1 parent 4269d0c commit a947170
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,18 @@ protected void onLoad() {

@Override
protected void onUnload() {
if (root != null) {
// Asynchronously schedule unmounting the root to allow React to finish the current render cycle.
// An unmounted root cannot be re-used, so first clear out this.root. If this widget is re-loaded, a new root will be created.
// Save a reference to the old root and schedule unmount asynchronously.
ReactDOMRoot oldRoot = this.root;
this.root = null;

if (oldRoot != null) {
// Asynchronously schedule unmounting the old root to allow React to finish the current render cycle.
// https://github.com/facebook/react/issues/25675
Timer t = new Timer() {
@Override
public void run() {
root.unmount();
root = null;
oldRoot.unmount();
}
};
t.schedule(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,17 @@ private void createRoot() {

private void destroyRoot() {
if (root != null) {
root.unmount();
root = null;
ReactDOMRoot oldRoot = this.root;
this.root = null;
// Asynchronously schedule unmounting the root to allow React to finish the current render cycle.
// https://github.com/facebook/react/issues/25675
Timer t = new Timer() {
@Override
public void run() {
oldRoot.unmount();
}
};
t.schedule(0);
}
}

Expand Down Expand Up @@ -184,21 +193,12 @@ public void render() {
// This component may be a React child of another component, so retrieve the root widget that renders this component tree.
ReactComponentV2<?, ?> componentToRender = getRootReactComponentWidget();

// Asynchronously schedule root operations in case the component is in the middle of an asynchronous render cycle
// See https://stackoverflow.com/questions/73459382
Timer t = new Timer() {
@Override
public void run() {
if (shouldDestroyRoot) {
destroyRoot();
}
if (shouldDestroyRoot) {
destroyRoot();
}

// Create a fresh ReactElement tree and render it
componentToRender.createRoot();
componentToRender.root.render(componentToRender.createReactElement());
}
};
t.schedule(0);
componentToRender.createRoot();
componentToRender.root.render(componentToRender.createReactElement());
}

@Override
Expand All @@ -221,15 +221,7 @@ protected void onUnload() {
// Detach any non-React descendants that were injected into the component tree
detachNonReactChildElements();

// Asynchronously schedule unmounting the root to allow React to finish the current render cycle.
// https://github.com/facebook/react/issues/25675
Timer t = new Timer() {
@Override
public void run() {
destroyRoot();
}
};
t.schedule(0);
destroyRoot();
}

/**
Expand Down

0 comments on commit a947170

Please sign in to comment.