From d23125366d7e2a9457f1742d9fcf8d1a018646aa Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Mon, 21 Sep 2020 00:54:33 +0100 Subject: [PATCH] Don't trigger lazy in DEV during element creation --- .../src/__tests__/ReactLazy-test.internal.js | 8 +------- packages/react/src/ReactElementValidator.js | 5 ++++- .../react/src/__tests__/ReactElementJSX-test.js | 14 ++++++++++++++ .../ReactElementValidator-test.internal.js | 10 ++++++++++ .../src/__tests__/ReactJSXElementValidator-test.js | 10 ++++++++++ packages/react/src/jsx/ReactJSXElementValidator.js | 5 ++++- 6 files changed, 43 insertions(+), 9 deletions(-) diff --git a/packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js b/packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js index 285eba5bd72e3..55c15e7412eab 100644 --- a/packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactLazy-test.internal.js @@ -979,13 +979,7 @@ describe('ReactLazy', () => { }, ); - if (__DEV__) { - // Getting the name for the warning cause the loading to start early. - expect(Scheduler).toHaveYielded(['Started loading']); - expect(Scheduler).toFlushAndYield(['Loading...']); - } else { - expect(Scheduler).toFlushAndYield(['Started loading', 'Loading...']); - } + expect(Scheduler).toFlushAndYield(['Started loading', 'Loading...']); expect(root).not.toMatchRenderedOutput(
AB
); await Promise.resolve(); diff --git a/packages/react/src/ReactElementValidator.js b/packages/react/src/ReactElementValidator.js index b63f454f94036..eee8ca26fe251 100644 --- a/packages/react/src/ReactElementValidator.js +++ b/packages/react/src/ReactElementValidator.js @@ -211,7 +211,6 @@ function validatePropTypes(element) { if (type === null || type === undefined || typeof type === 'string') { return; } - const name = getComponentName(type); let propTypes; if (typeof type === 'function') { propTypes = type.propTypes; @@ -227,9 +226,13 @@ function validatePropTypes(element) { return; } if (propTypes) { + // Intentionally inside to avoid triggering lazy initializers: + const name = getComponentName(type); checkPropTypes(propTypes, element.props, 'prop', name, element); } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) { propTypesMisspellWarningShown = true; + // Intentionally inside to avoid triggering lazy initializers: + const name = getComponentName(type); console.error( 'Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', name || 'Unknown', diff --git a/packages/react/src/__tests__/ReactElementJSX-test.js b/packages/react/src/__tests__/ReactElementJSX-test.js index 04bf8e1773585..5932209d0c578 100644 --- a/packages/react/src/__tests__/ReactElementJSX-test.js +++ b/packages/react/src/__tests__/ReactElementJSX-test.js @@ -415,4 +415,18 @@ describe('ReactElement.jsx', () => { // TODO: an explicit expect for no warning? ReactDOM.render(JSXRuntime.jsx(Parent, {}), container); }); + + it('does not call lazy initializers eagerly', () => { + let didCall = false; + const Lazy = React.lazy(() => { + didCall = true; + return {then() {}}; + }); + if (__DEV__) { + JSXDEVRuntime.jsxDEV(Lazy, {}); + } else { + JSXRuntime.jsx(Lazy, {}); + } + expect(didCall).toBe(false); + }); }); diff --git a/packages/react/src/__tests__/ReactElementValidator-test.internal.js b/packages/react/src/__tests__/ReactElementValidator-test.internal.js index ee5a3c66bc1e8..2d46827bcfb26 100644 --- a/packages/react/src/__tests__/ReactElementValidator-test.internal.js +++ b/packages/react/src/__tests__/ReactElementValidator-test.internal.js @@ -532,4 +532,14 @@ describe('ReactElementValidator', () => { {withoutStack: true}, ); }); + + it('does not call lazy initializers eagerly', () => { + let didCall = false; + const Lazy = React.lazy(() => { + didCall = true; + return {then() {}}; + }); + React.createElement(Lazy); + expect(didCall).toBe(false); + }); }); diff --git a/packages/react/src/__tests__/ReactJSXElementValidator-test.js b/packages/react/src/__tests__/ReactJSXElementValidator-test.js index a0f9640b10b06..a94adbb1ad0a6 100644 --- a/packages/react/src/__tests__/ReactJSXElementValidator-test.js +++ b/packages/react/src/__tests__/ReactJSXElementValidator-test.js @@ -417,4 +417,14 @@ describe('ReactJSXElementValidator', () => { withoutStack: true, }); }); + + it('does not call lazy initializers eagerly', () => { + let didCall = false; + const Lazy = React.lazy(() => { + didCall = true; + return {then() {}}; + }); + ; + expect(didCall).toBe(false); + }); }); diff --git a/packages/react/src/jsx/ReactJSXElementValidator.js b/packages/react/src/jsx/ReactJSXElementValidator.js index 18a7cdd186299..b76baa1e353a9 100644 --- a/packages/react/src/jsx/ReactJSXElementValidator.js +++ b/packages/react/src/jsx/ReactJSXElementValidator.js @@ -227,7 +227,6 @@ function validatePropTypes(element) { if (type === null || type === undefined || typeof type === 'string') { return; } - const name = getComponentName(type); let propTypes; if (typeof type === 'function') { propTypes = type.propTypes; @@ -243,9 +242,13 @@ function validatePropTypes(element) { return; } if (propTypes) { + // Intentionally inside to avoid triggering lazy initializers: + const name = getComponentName(type); checkPropTypes(propTypes, element.props, 'prop', name, element); } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) { propTypesMisspellWarningShown = true; + // Intentionally inside to avoid triggering lazy initializers: + const name = getComponentName(type); console.error( 'Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', name || 'Unknown',