Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Root API should clear non-empty roots before mounting #18730

Merged

Conversation

bvaughn
Copy link
Contributor

@bvaughn bvaughn commented Apr 24, 2020

Legacy render-into-subtree API removes children from a container before rendering into it:

function legacyCreateRootFromDOMContainer(
container: Container,
forceHydrate: boolean,
): RootType {
const shouldHydrate =
forceHydrate || shouldHydrateDueToLegacyHeuristic(container);
// First clear any existing content.
if (!shouldHydrate) {
let warned = false;
let rootSibling;
while ((rootSibling = container.lastChild)) {
if (__DEV__) {
if (
!warned &&
rootSibling.nodeType === ELEMENT_NODE &&
(rootSibling: any).hasAttribute(ROOT_ATTRIBUTE_NAME)
) {
warned = true;
console.error(
'render(): Target node has markup rendered by React, but there ' +
'are unrelated nodes as well. This is most commonly caused by ' +
'white-space inserted around server-rendered markup.',
);
}
}
container.removeChild(rootSibling);

The createRoot API did not do this. Instead it left previous children around in the document forever. This commit brings the createRoot API into alignment with render - with a small exception. Pre-existing container children don't get cleared until the commit phase.

Note that this PR introduces a new DOM host config method, clearContainer, that may be used by the useMutableSource hook as well in the case of hydration (see #18183)

@facebook-github-bot facebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Apr 24, 2020
@codesandbox-ci
Copy link

codesandbox-ci bot commented Apr 24, 2020

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit f45a8a1:

Sandbox Source
quirky-margulis-999dx Configuration

@bvaughn
Copy link
Contributor Author

bvaughn commented Apr 25, 2020

Seb and I chatted about this out of band yesterday. He suggested trying a different approach- putting an effect on the HostRoot during the complete phase if current.child is null (meaning either a mount or an update after a previous render with no React children).

This works (in that it fixes the new test I added) but is also a lot broader than my initial approach. Several tests failing. Going to dig in and see if the failures are improvements or road blocks for the approach.

This also requires implementing clearContainer methods for some renderers that I'm unsure of how to implement, like ART and React Native. For ART, I'm not sure how to handle any case other than SVG. For React Native, I'm not sure how to handle any case- since the "container" is just a number, and UIManager.manageChildren expects a list of all indices to clear. There is no "remove all" type method on UIManager.

@bvaughn
Copy link
Contributor Author

bvaughn commented Apr 25, 2020

One test case this breaks is in ReactServerRenderingHydration-test:

it('Suspense + hydration in legacy mode with no fallback', () => {
  const element = document.createElement('div');
  element.innerHTML = '<div>Hello World</div>';
  const div = element.firstChild;
  const ref = React.createRef();
  ReactDOM.hydrate(
    <React.Suspense>
      <div ref={ref}>Hello World</div>
    </React.Suspense>,
    element,
  );

  // Because this didn't have a fallback, it was hydrated as if it's
  // not a Suspense boundary.
  expect(ref.current).toBe(div);
  expect(element.innerHTML).toBe('<div>Hello World</div>');
});

In this case, popHydrationState() does not think it's hydrating because fiber is the HostRoot but hydrationParentFiber points to the Suspense node. So as a result, we clear the container.

@sebmarkbage
Copy link
Collaborator

Can you push the code for the new approach?

@gaearon
Copy link
Collaborator

gaearon commented Apr 25, 2020

Last time we discussed this, I think the conclusion was that maybe it shouldn't clear until commit, at which point we should replace. So that you can leave an HTML shim there that would be replaced. But maybe this isn't that useful.

@gaearon
Copy link
Collaborator

gaearon commented Apr 25, 2020

I guess that's what you're doing.

@bvaughn
Copy link
Contributor Author

bvaughn commented Apr 25, 2020

Last time we discussed this, I think the conclusion was that maybe it shouldn't clear until commit, at which point we should replace. So that you can leave an HTML shim there that would be replaced. But maybe this isn't that useful.

That's what this PR is implementing. (And what my local commit that I haven't pushed yet is implementing in a different way, via a new effect type).

@bvaughn
Copy link
Contributor Author

bvaughn commented Apr 25, 2020

Can you push the code for the new approach?

@sebmarkbage Sure. It breaks lots of persistence tests too which I haven't had the chance to dig into yet.

@bvaughn bvaughn force-pushed the always-clear-non-empty-root-container branch 3 times, most recently from 572669a to 88d6d34 Compare April 25, 2020 18:10
@bvaughn
Copy link
Contributor Author

bvaughn commented Apr 25, 2020

Okay, I think every test is passing now except for the one I mentioned above.

Still an open question about React Native and React ART configs.

Copy link
Collaborator

@sebmarkbage sebmarkbage left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you reuse the Update effectTag?

It would be better to add something on the fiber state or root itself rather than add a new effect tag since we’ve hit effect tag bankruptcy.

@bvaughn
Copy link
Contributor Author

bvaughn commented Apr 25, 2020

Can you reuse the Update effectTag?

Update effect would happen too late, right? The container would just end up clearing all of its newly created (by React) contents.

Unless you're suggesting I call commitBeforeMutationLifeCycles with Update effects too, and just handle the HostRoot there. That seems sketchy though because we also handle Update for HostRoot in commitWork --- so we would have to switch based on root.hydrate which feels pretty fragile.

@sebmarkbage
Copy link
Collaborator

sebmarkbage commented Apr 25, 2020

I think we can’t do this for Portals because people (FB) are using document.body as the container for many Portals. This is kind of unfortunate for a number of event related things and selective hydration but it’s pretty common. It’s likely that a SSR compatible api for portals would require other semantics anyway since there’s no scope of what body knows are hydratable.

So that settles that.

@bvaughn
Copy link
Contributor Author

bvaughn commented Apr 25, 2020

CI failure is expected still until I figure out what to do about that one failing test.

Probably going to step away for a bit and go running or something 😄

@bvaughn bvaughn force-pushed the always-clear-non-empty-root-container branch from 09440f4 to 752d60c Compare April 25, 2020 20:27
Brian Vaughn added 4 commits April 27, 2020 08:22
Legacy render-into-subtree API removes children from a container before rendering into it. The root API did not do this previously, but just left the children around in the document.

This commit adds a new FiberRoot flag to clear a container's contents before mounting. This is done during the commit phase, to avoid multiple, observable mutations.
This avoids breaking support for ReactDOM.hydration in legacy mode with no fallback.
@bvaughn
Copy link
Contributor Author

bvaughn commented Apr 27, 2020

Okay. Tests are passing.

Still an open question about React Native and React ART configs.

Think it's ready for review/feedback.

@bvaughn bvaughn force-pushed the always-clear-non-empty-root-container branch from 752d60c to f318360 Compare April 27, 2020 15:29
@sizebot
Copy link

sizebot commented Apr 27, 2020

Details of bundled changes.

Comparing: f342a23...f45a8a1

react-test-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-test-renderer.development.js +0.2% +0.2% 571.79 KB 572.68 KB 119.29 KB 119.51 KB UMD_DEV
react-test-renderer.production.min.js 🔺+0.2% 🔺+0.2% 74.49 KB 74.62 KB 22.72 KB 22.76 KB UMD_PROD
react-test-renderer-shallow.development.js 0.0% -0.0% 39.07 KB 39.07 KB 9.55 KB 9.55 KB UMD_DEV
react-test-renderer-shallow.production.min.js 0.0% 0.0% 12.74 KB 12.74 KB 3.97 KB 3.97 KB UMD_PROD
react-test-renderer.development.js +0.2% +0.2% 545.17 KB 546.02 KB 117.89 KB 118.13 KB NODE_DEV
react-test-renderer.production.min.js 🔺+0.2% 🔺+0.1% 74.29 KB 74.42 KB 22.4 KB 22.43 KB NODE_PROD
ReactTestRenderer-dev.js +0.1% +0.2% 572.18 KB 572.99 KB 121.2 KB 121.42 KB FB_WWW_DEV

react-dom

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-dom.profiling.min.js +0.1% +0.1% 128.79 KB 128.96 KB 40.29 KB 40.32 KB NODE_PROFILING
ReactDOM-dev.js +0.1% +0.1% 1012.57 KB 1013.57 KB 225.64 KB 225.88 KB FB_WWW_DEV
ReactDOMServer-dev.js 0.0% -0.0% 160.27 KB 160.27 KB 40.83 KB 40.83 KB FB_WWW_DEV
ReactDOM-prod.js 🔺+0.1% 🔺+0.1% 420.4 KB 420.78 KB 73.8 KB 73.86 KB FB_WWW_PROD
ReactDOM-profiling.js +0.1% +0.1% 431.3 KB 431.68 KB 75.64 KB 75.68 KB FB_WWW_PROFILING
react-dom-unstable-fizz.node.development.js 0.0% -0.1% 5.51 KB 5.51 KB 1.83 KB 1.83 KB NODE_DEV
react-dom-unstable-fizz.browser.development.js 0.0% -0.1% 5.26 KB 5.26 KB 1.78 KB 1.77 KB UMD_DEV
ReactDOMTesting-dev.js +0.1% +0.1% 908.69 KB 909.7 KB 202.8 KB 203.04 KB FB_WWW_DEV
ReactDOMTesting-prod.js 🔺+0.1% 🔺+0.1% 378.29 KB 378.67 KB 69.13 KB 69.17 KB FB_WWW_PROD
ReactDOMTesting-profiling.js +0.1% +0.1% 378.29 KB 378.67 KB 69.13 KB 69.17 KB FB_WWW_PROFILING
react-dom-unstable-fizz.browser.development.js 0.0% -0.1% 4.77 KB 4.77 KB 1.67 KB 1.67 KB NODE_DEV
react-dom-test-utils.production.min.js 0.0% -0.0% 13.12 KB 13.12 KB 4.81 KB 4.81 KB NODE_PROD
react-dom-server.node.production.min.js 0.0% -0.0% 23.7 KB 23.7 KB 8.74 KB 8.74 KB NODE_PROD
react-dom.development.js +0.1% +0.1% 940.71 KB 941.81 KB 205.83 KB 206.08 KB UMD_DEV
react-dom-server.browser.development.js 0.0% -0.0% 162.17 KB 162.17 KB 41.27 KB 41.26 KB UMD_DEV
react-dom.production.min.js 🔺+0.1% 🔺+0.1% 124.58 KB 124.74 KB 39.92 KB 39.95 KB UMD_PROD
ReactDOMForked-dev.js +0.1% +0.1% 1007.85 KB 1008.86 KB 224.26 KB 224.55 KB FB_WWW_DEV
react-dom.profiling.min.js +0.1% +0.1% 128.45 KB 128.62 KB 41.06 KB 41.09 KB UMD_PROFILING
ReactDOMForked-prod.js 🔺+0.1% 🔺+0.1% 421.74 KB 422.12 KB 73.97 KB 74.01 KB FB_WWW_PROD
react-dom.development.js +0.1% +0.1% 895.61 KB 896.65 KB 203.31 KB 203.55 KB NODE_DEV
ReactDOMForked-profiling.js +0.1% +0.1% 432.08 KB 432.46 KB 75.7 KB 75.73 KB FB_WWW_PROFILING
react-dom-server.browser.development.js 0.0% -0.0% 152.66 KB 152.66 KB 40.49 KB 40.49 KB NODE_DEV
react-dom.production.min.js 🔺+0.1% 🔺+0.1% 124.78 KB 124.94 KB 39.02 KB 39.05 KB NODE_PROD

react-art

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
ReactART-dev.js +0.1% +0.2% 597.7 KB 598.51 KB 125.93 KB 126.15 KB FB_WWW_DEV
ReactART-prod.js 🔺+0.1% 0.0% 241.94 KB 242.09 KB 41.33 KB 41.34 KB FB_WWW_PROD
react-art.development.js +0.1% +0.2% 659.22 KB 660.1 KB 138.97 KB 139.21 KB UMD_DEV
react-art.production.min.js 🔺+0.1% 0.0% 110.81 KB 110.87 KB 33.6 KB 33.6 KB UMD_PROD
react-art.development.js +0.2% +0.2% 562.47 KB 563.32 KB 121.44 KB 121.69 KB NODE_DEV
react-art.production.min.js 🔺+0.1% 0.0% 75.75 KB 75.82 KB 22.79 KB 22.79 KB NODE_PROD

react-native-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
ReactNativeRenderer-dev.js +0.1% +0.2% 661.08 KB 661.96 KB 142.04 KB 142.3 KB RN_FB_DEV
ReactNativeRenderer-prod.js 🔺+0.1% 0.0% 271.99 KB 272.14 KB 46.98 KB 47 KB RN_FB_PROD
ReactNativeRenderer-profiling.js +0.1% 0.0% 283.43 KB 283.58 KB 49.2 KB 49.22 KB RN_FB_PROFILING
ReactFabric-dev.js +0.1% +0.1% 637.61 KB 638.2 KB 136.78 KB 136.95 KB RN_OSS_DEV
ReactFabric-prod.js 🔺+0.1% 0.0% 263.76 KB 263.91 KB 45.44 KB 45.45 KB RN_OSS_PROD
ReactFabric-profiling.js +0.1% 0.0% 275.19 KB 275.33 KB 47.64 KB 47.65 KB RN_OSS_PROFILING
ReactFabric-dev.js +0.1% +0.1% 642.43 KB 643.01 KB 137.54 KB 137.72 KB RN_FB_DEV
ReactFabric-prod.js 🔺+0.1% 0.0% 263.92 KB 264.06 KB 45.47 KB 45.48 KB RN_FB_PROD
ReactNativeRenderer-dev.js +0.1% +0.2% 656.27 KB 657.16 KB 141.25 KB 141.51 KB RN_OSS_DEV
ReactFabric-profiling.js +0.1% 0.0% 275.34 KB 275.48 KB 47.67 KB 47.68 KB RN_FB_PROFILING
ReactNativeRenderer-prod.js 🔺+0.1% 0.0% 271.84 KB 271.99 KB 46.95 KB 46.97 KB RN_OSS_PROD
ReactNativeRenderer-profiling.js +0.1% 0.0% 283.29 KB 283.44 KB 49.18 KB 49.19 KB RN_OSS_PROFILING

react-reconciler

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-reconciler.development.js +0.1% +0.2% 605.81 KB 606.67 KB 128.46 KB 128.66 KB NODE_DEV
react-reconciler.production.min.js 🔺+0.1% 0.0% 81.39 KB 81.51 KB 24.13 KB 24.14 KB NODE_PROD

Size changes (experimental)

Generated by 🚫 dangerJS against f45a8a1

@sizebot
Copy link

sizebot commented Apr 27, 2020

Details of bundled changes.

Comparing: f342a23...f45a8a1

react-dom

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-dom.production.min.js 🔺+0.1% 🔺+0.1% 119.86 KB 120.03 KB 37.6 KB 37.63 KB NODE_PROD
ReactDOMTesting-profiling.js +0.1% +0.1% 390.15 KB 390.52 KB 71.11 KB 71.15 KB FB_WWW_PROFILING
react-dom-server.node.production.min.js 0.0% -0.0% 23.24 KB 23.24 KB 8.66 KB 8.66 KB NODE_PROD
react-dom.profiling.min.js +0.1% +0.1% 123.76 KB 123.92 KB 38.77 KB 38.81 KB NODE_PROFILING
react-dom-unstable-fizz.browser.development.js 0.0% -0.1% 4.75 KB 4.75 KB 1.67 KB 1.67 KB NODE_DEV
ReactDOMForked-dev.js +0.1% +0.1% 1.01 MB 1.01 MB 229.92 KB 230.21 KB FB_WWW_DEV
ReactDOMForked-prod.js 🔺+0.1% 0.0% 433.2 KB 433.58 KB 75.97 KB 76.01 KB FB_WWW_PROD
react-dom.development.js +0.1% +0.1% 906.83 KB 907.92 KB 199.37 KB 199.62 KB UMD_DEV
ReactDOMForked-profiling.js +0.1% 0.0% 443.61 KB 443.98 KB 77.72 KB 77.75 KB FB_WWW_PROFILING
react-dom.production.min.js 🔺+0.1% 🔺+0.1% 119.74 KB 119.9 KB 38.38 KB 38.42 KB UMD_PROD
react-dom.profiling.min.js +0.1% +0.1% 123.5 KB 123.67 KB 39.61 KB 39.64 KB UMD_PROFILING
ReactDOMTesting-dev.js +0.1% +0.1% 934.49 KB 935.49 KB 208.43 KB 208.68 KB FB_WWW_DEV
react-dom.development.js +0.1% +0.1% 863.17 KB 864.22 KB 196.83 KB 197.08 KB NODE_DEV
ReactDOMTesting-prod.js 🔺+0.1% 🔺+0.1% 390.15 KB 390.52 KB 71.11 KB 71.15 KB FB_WWW_PROD
ReactDOM-dev.js +0.1% +0.1% 1.01 MB 1.01 MB 231.3 KB 231.56 KB FB_WWW_DEV
ReactDOM-prod.js 🔺+0.1% 🔺+0.1% 431.87 KB 432.24 KB 75.79 KB 75.86 KB FB_WWW_PROD
react-dom-unstable-fizz.node.development.js 0.0% -0.1% 5.5 KB 5.5 KB 1.83 KB 1.82 KB NODE_DEV
ReactDOM-profiling.js +0.1% 0.0% 442.83 KB 443.2 KB 77.67 KB 77.71 KB FB_WWW_PROFILING
react-dom-test-utils.production.min.js 0.0% -0.0% 13.1 KB 13.1 KB 4.8 KB 4.8 KB NODE_PROD
react-dom-server.browser.development.js 0.0% 0.0% 154.86 KB 154.86 KB 39.47 KB 39.47 KB UMD_DEV
react-dom-unstable-fizz.node.production.min.js 0.0% -0.2% 1.16 KB 1.16 KB 660 B 659 B NODE_PROD
react-dom-server.browser.production.min.js 0.0% -0.0% 22.83 KB 22.83 KB 8.5 KB 8.5 KB NODE_PROD
react-dom-unstable-fizz.browser.development.js 0.0% +0.1% 5.25 KB 5.25 KB 1.76 KB 1.77 KB UMD_DEV

react-native-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
ReactNativeRenderer-dev.js +0.1% +0.2% 656.26 KB 657.15 KB 141.25 KB 141.51 KB RN_OSS_DEV
ReactNativeRenderer-prod.js 🔺+0.1% 0.0% 271.83 KB 271.98 KB 46.94 KB 46.96 KB RN_OSS_PROD
ReactNativeRenderer-profiling.js +0.1% 0.0% 283.28 KB 283.42 KB 49.17 KB 49.18 KB RN_OSS_PROFILING
ReactFabric-dev.js +0.1% +0.1% 637.6 KB 638.19 KB 136.77 KB 136.95 KB RN_OSS_DEV
ReactFabric-prod.js 🔺+0.1% 0.0% 263.75 KB 263.9 KB 45.43 KB 45.44 KB RN_OSS_PROD
ReactFabric-profiling.js +0.1% 0.0% 275.17 KB 275.32 KB 47.63 KB 47.64 KB RN_OSS_PROFILING

react-art

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-art.development.js +0.2% +0.2% 539.15 KB 540 KB 116.53 KB 116.76 KB NODE_DEV
react-art.production.min.js 🔺+0.1% 🔺+0.1% 72.44 KB 72.5 KB 21.77 KB 21.79 KB NODE_PROD
ReactART-dev.js +0.1% +0.2% 607.71 KB 608.53 KB 127.97 KB 128.18 KB FB_WWW_DEV
ReactART-prod.js 🔺+0.1% 0.0% 248.98 KB 249.12 KB 42.58 KB 42.59 KB FB_WWW_PROD
react-art.development.js +0.1% +0.2% 634.89 KB 635.77 KB 134.11 KB 134.33 KB UMD_DEV
react-art.production.min.js 🔺+0.1% 🔺+0.1% 107.44 KB 107.5 KB 32.6 KB 32.63 KB UMD_PROD

react-test-renderer

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-test-renderer-shallow.development.js 0.0% -0.0% 39.05 KB 39.05 KB 9.54 KB 9.54 KB UMD_DEV
react-test-renderer-shallow.production.min.js 0.0% 🔺+0.1% 12.73 KB 12.73 KB 3.96 KB 3.97 KB UMD_PROD
react-test-renderer.development.js +0.2% +0.2% 545.14 KB 546 KB 117.88 KB 118.12 KB NODE_DEV
react-test-renderer.production.min.js 🔺+0.2% 🔺+0.1% 74.27 KB 74.39 KB 22.38 KB 22.41 KB NODE_PROD
ReactTestRenderer-dev.js +0.1% +0.2% 572.16 KB 572.98 KB 121.19 KB 121.42 KB FB_WWW_DEV
react-test-renderer.development.js +0.2% +0.2% 571.77 KB 572.66 KB 119.28 KB 119.5 KB UMD_DEV
react-test-renderer.production.min.js 🔺+0.2% 🔺+0.2% 74.47 KB 74.59 KB 22.7 KB 22.74 KB UMD_PROD

react-reconciler

File Filesize Diff Gzip Diff Prev Size Current Size Prev Gzip Current Gzip ENV
react-reconciler.development.js +0.1% +0.2% 580.12 KB 580.98 KB 123.07 KB 123.27 KB NODE_DEV
react-reconciler.production.min.js 🔺+0.1% 🔺+0.1% 77.66 KB 77.78 KB 23.08 KB 23.1 KB NODE_PROD

Size changes (stable)

Generated by 🚫 dangerJS against f45a8a1

@bvaughn
Copy link
Contributor Author

bvaughn commented Apr 27, 2020

DevTools CI failure is unrelated to this PR. Looks like a transient issue.

@bvaughn bvaughn requested a review from trueadm April 28, 2020 16:17
@trueadm
Copy link
Contributor

trueadm commented Apr 28, 2020

Was @sebmarkbage's comment above addressed?

I think we can’t do this for Portals because people (FB) are using document.body as the container for many Portals.

@bvaughn
Copy link
Contributor Author

bvaughn commented Apr 28, 2020

Was @sebmarkbage's comment above addressed?

I think we can’t do this for Portals because people (FB) are using document.body as the container for many Portals.

Seb's comment doesn't require any action, does it? This change only applies to HostRoots. I don't do anything new for HostPortals.

I think he was just saying that it wouldn't work for portals after all (referring to this earlier comment).

@trueadm
Copy link
Contributor

trueadm commented Apr 28, 2020

Thanks for clarifying!

Does this also cover the case where we mount to a comment node? I know we do it a lot internally, but I wasn't sure if we wanted to keep supporting it in the future. I think @sebmarkbage mentioned that we no longer want to support comment nodes with the new API. I'll approve but maybe we should add a warning/error/test if they're used. I also left some more comments on different ways to improve perf.

@bvaughn
Copy link
Contributor Author

bvaughn commented Apr 28, 2020

I only explicitly check for ELEMENT_NODE and DOCUMENT_NODE.

I don't think there would be anything to do here in the case of a comment node, since comment nodes can't contain children.

In other places in the host config file, when we see a comment node, we grab the parentNode instead (to get a thing we can append/remove children from). This new method only needs to clear pre-existing children though, so I think it doesn't care about comment nodes.

@bvaughn bvaughn force-pushed the always-clear-non-empty-root-container branch from 0cc80fa to f45a8a1 Compare April 28, 2020 17:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed React Core Team Opened by a member of the React Core Team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants