diff --git a/src/renderers/__tests__/ReactUpdates-test.js b/src/renderers/__tests__/ReactUpdates-test.js index 16812b3aba9dd..ead339ba85587 100644 --- a/src/renderers/__tests__/ReactUpdates-test.js +++ b/src/renderers/__tests__/ReactUpdates-test.js @@ -522,10 +522,7 @@ describe('ReactUpdates', () => { var portal = null; // If we're using Fiber, we use Portals instead to achieve this. if (ReactDOMFeatureFlags.useFiber) { - portal = ReactDOM.unstable_createPortal( - (b = n)} />, - bContainer, - ); + portal = ReactDOM.createPortal( (b = n)} />, bContainer); } return
A{this.state.x}{portal}
; } diff --git a/src/renderers/dom/__tests__/ReactDOMProduction-test.js b/src/renderers/dom/__tests__/ReactDOMProduction-test.js index 422ee37104559..d34da33cc539d 100644 --- a/src/renderers/dom/__tests__/ReactDOMProduction-test.js +++ b/src/renderers/dom/__tests__/ReactDOMProduction-test.js @@ -246,10 +246,7 @@ describe('ReactDOMProduction', () => { var expectSVG = {ref: el => svgEls.push(el)}; var expectHTML = {ref: el => htmlEls.push(el)}; var usePortal = function(tree) { - return ReactDOM.unstable_createPortal( - tree, - document.createElement('div'), - ); + return ReactDOM.createPortal(tree, document.createElement('div')); }; var assertNamespacesMatch = function(tree) { var container = document.createElement('div'); diff --git a/src/renderers/dom/fiber/ReactDOMFiberEntry.js b/src/renderers/dom/fiber/ReactDOMFiberEntry.js index 322a8262dfd3a..4e17cf72d9a8e 100644 --- a/src/renderers/dom/fiber/ReactDOMFiberEntry.js +++ b/src/renderers/dom/fiber/ReactDOMFiberEntry.js @@ -646,7 +646,22 @@ function renderSubtreeIntoContainer( return DOMRenderer.getPublicRootInstance(root); } +function createPortal( + children: ReactNodeList, + container: DOMContainer, + key: ?string = null, +) { + invariant( + isValidContainer(container), + 'Target container is not a DOM element.', + ); + // TODO: pass ReactDOM portal implementation as third argument + return ReactPortal.createPortal(children, container, null, key); +} + var ReactDOMFiber = { + createPortal, + hydrate(element: React$Node, container: DOMContainer, callback: ?Function) { // TODO: throw or warn if we couldn't hydrate? return renderSubtreeIntoContainer(null, element, container, true, callback); @@ -742,14 +757,9 @@ var ReactDOMFiber = { findDOMNode: findDOMNode, - unstable_createPortal( - children: ReactNodeList, - container: DOMContainer, - key: ?string = null, - ) { - // TODO: pass ReactDOM portal implementation as third argument - return ReactPortal.createPortal(children, container, null, key); - }, + // Temporary alias since we already shipped React 16 RC with it. + // TODO: remove in React 17. + unstable_createPortal: createPortal, unstable_batchedUpdates: ReactGenericBatching.batchedUpdates, diff --git a/src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js b/src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js index aabaeae11fc41..4c90d2c65496d 100644 --- a/src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js +++ b/src/renderers/dom/fiber/__tests__/ReactDOMFiber-test.js @@ -182,10 +182,7 @@ describe('ReactDOMFiber', () => { var expectMath = {ref: el => mathEls.push(el)}; var usePortal = function(tree) { - return ReactDOM.unstable_createPortal( - tree, - document.createElement('div'), - ); + return ReactDOM.createPortal(tree, document.createElement('div')); }; var assertNamespacesMatch = function(tree) { @@ -212,6 +209,24 @@ describe('ReactDOMFiber', () => { it('should render one portal', () => { var portalContainer = document.createElement('div'); + ReactDOM.render( +
+ {ReactDOM.createPortal(
portal
, portalContainer)} +
, + container, + ); + expect(portalContainer.innerHTML).toBe('
portal
'); + expect(container.innerHTML).toBe('
'); + + ReactDOM.unmountComponentAtNode(container); + expect(portalContainer.innerHTML).toBe(''); + expect(container.innerHTML).toBe(''); + }); + + // TODO: remove in React 17 + it('should support unstable_createPortal alias', () => { + var portalContainer = document.createElement('div'); + ReactDOM.render(
{ReactDOM.unstable_createPortal(
portal
, portalContainer)} @@ -260,12 +275,12 @@ describe('ReactDOMFiber', () => { const {step} = this.props; return [ , - ReactDOM.unstable_createPortal( + ReactDOM.createPortal( , portalContainer1, ), , - ReactDOM.unstable_createPortal( + ReactDOM.createPortal( [ , , @@ -334,14 +349,14 @@ describe('ReactDOMFiber', () => { ReactDOM.render( [
normal[0]
, - ReactDOM.unstable_createPortal( + ReactDOM.createPortal( [
portal1[0]
, - ReactDOM.unstable_createPortal( + ReactDOM.createPortal(
portal2[0]
, portalContainer2, ), - ReactDOM.unstable_createPortal( + ReactDOM.createPortal(
portal3[0]
, portalContainer3, ), @@ -374,7 +389,7 @@ describe('ReactDOMFiber', () => { ReactDOM.render(
- {ReactDOM.unstable_createPortal(
portal:1
, portalContainer)} + {ReactDOM.createPortal(
portal:1
, portalContainer)}
, container, ); @@ -383,7 +398,7 @@ describe('ReactDOMFiber', () => { ReactDOM.render(
- {ReactDOM.unstable_createPortal(
portal:2
, portalContainer)} + {ReactDOM.createPortal(
portal:2
, portalContainer)}
, container, ); @@ -392,7 +407,7 @@ describe('ReactDOMFiber', () => { ReactDOM.render(
- {ReactDOM.unstable_createPortal(

portal:3

, portalContainer)} + {ReactDOM.createPortal(

portal:3

, portalContainer)}
, container, ); @@ -401,7 +416,7 @@ describe('ReactDOMFiber', () => { ReactDOM.render(
- {ReactDOM.unstable_createPortal(['Hi', 'Bye'], portalContainer)} + {ReactDOM.createPortal(['Hi', 'Bye'], portalContainer)}
, container, ); @@ -410,7 +425,7 @@ describe('ReactDOMFiber', () => { ReactDOM.render(
- {ReactDOM.unstable_createPortal(['Bye', 'Hi'], portalContainer)} + {ReactDOM.createPortal(['Bye', 'Hi'], portalContainer)}
, container, ); @@ -419,7 +434,7 @@ describe('ReactDOMFiber', () => { ReactDOM.render(
- {ReactDOM.unstable_createPortal(null, portalContainer)} + {ReactDOM.createPortal(null, portalContainer)}
, container, ); @@ -700,7 +715,7 @@ describe('ReactDOMFiber', () => { } render() { - return ReactDOM.unstable_createPortal(, portalContainer); + return ReactDOM.createPortal(, portalContainer); } } @@ -741,7 +756,7 @@ describe('ReactDOMFiber', () => { } render() { - return ReactDOM.unstable_createPortal(, portalContainer); + return ReactDOM.createPortal(, portalContainer); } } @@ -781,7 +796,7 @@ describe('ReactDOMFiber', () => { } render() { - return ReactDOM.unstable_createPortal(, portalContainer); + return ReactDOM.createPortal(, portalContainer); } } @@ -821,7 +836,7 @@ describe('ReactDOMFiber', () => { ReactDOM.render(
ops.push('parent clicked')}> - {ReactDOM.unstable_createPortal( + {ReactDOM.createPortal(
ops.push('portal clicked')} ref={n => (portal = n)}> @@ -874,7 +889,7 @@ describe('ReactDOMFiber', () => { onMouseEnter={() => ops.push('enter parent')} onMouseLeave={() => ops.push('leave parent')}>
(firstTarget = n)} /> - {ReactDOM.unstable_createPortal( + {ReactDOM.createPortal(
ops.push('enter portal')} onMouseLeave={() => ops.push('leave portal')} @@ -909,6 +924,15 @@ describe('ReactDOMFiber', () => { ]); }); + it('should throw on bad createPortal argument', () => { + expect(() => { + ReactDOM.createPortal(
portal
, null); + }).toThrow('Target container is not a DOM element.'); + expect(() => { + ReactDOM.createPortal(
portal
, document.createTextNode('hi')); + }).toThrow('Target container is not a DOM element.'); + }); + it('should warn for non-functional event listeners', () => { spyOn(console, 'error'); class Example extends React.Component { diff --git a/src/renderers/dom/shared/__tests__/renderSubtreeIntoContainer-test.js b/src/renderers/dom/shared/__tests__/renderSubtreeIntoContainer-test.js index cca63bffa77f1..55b89c036979e 100644 --- a/src/renderers/dom/shared/__tests__/renderSubtreeIntoContainer-test.js +++ b/src/renderers/dom/shared/__tests__/renderSubtreeIntoContainer-test.js @@ -319,7 +319,7 @@ describe('renderSubtreeIntoContainer', () => { 'a React 15 tree inside a React 16 tree using ' + "unstable_renderSubtreeIntoContainer, which isn't supported. Try to " + 'make sure you have only one copy of React (and ideally, switch to ' + - 'ReactDOM.unstable_createPortal).', + 'ReactDOM.createPortal).', ); }); } diff --git a/src/renderers/native/ReactNativeFiberEntry.js b/src/renderers/native/ReactNativeFiberEntry.js index d0f119cbde6a2..6c55fdc0a14cc 100644 --- a/src/renderers/native/ReactNativeFiberEntry.js +++ b/src/renderers/native/ReactNativeFiberEntry.js @@ -79,7 +79,7 @@ const ReactNativeFiber: ReactNativeType = { UIManager.removeRootView(containerTag); }, - unstable_createPortal( + createPortal( children: ReactNodeList, containerTag: number, key: ?string = null, diff --git a/src/renderers/shared/fiber/ReactFiberClassComponent.js b/src/renderers/shared/fiber/ReactFiberClassComponent.js index e726cfd56928e..e9128f5f93b8f 100644 --- a/src/renderers/shared/fiber/ReactFiberClassComponent.js +++ b/src/renderers/shared/fiber/ReactFiberClassComponent.js @@ -71,7 +71,7 @@ if (__DEV__) { 'a React 15 tree inside a React 16 tree using ' + "unstable_renderSubtreeIntoContainer, which isn't supported. Try " + 'to make sure you have only one copy of React (and ideally, switch ' + - 'to ReactDOM.unstable_createPortal).', + 'to ReactDOM.createPortal).', ); }, });