diff --git a/packages/react-dom/src/__tests__/ReactDeprecationWarnings-test.internal.js b/packages/react-dom/src/__tests__/ReactDeprecationWarnings-test.internal.js index d4413dd4e87..9d29ef5a34c 100644 --- a/packages/react-dom/src/__tests__/ReactDeprecationWarnings-test.internal.js +++ b/packages/react-dom/src/__tests__/ReactDeprecationWarnings-test.internal.js @@ -10,20 +10,24 @@ 'use strict'; let React; -let ReactTestUtils; let ReactFeatureFlags; +let ReactNoop; +let Scheduler; describe('ReactDeprecationWarnings', () => { beforeEach(() => { jest.resetModules(); React = require('react'); ReactFeatureFlags = require('shared/ReactFeatureFlags'); - ReactTestUtils = require('react-dom/test-utils'); + ReactNoop = require('react-noop-renderer'); + Scheduler = require('scheduler'); ReactFeatureFlags.warnAboutDefaultPropsOnFunctionComponents = true; + ReactFeatureFlags.warnAboutStringRefs = true; }); afterEach(() => { ReactFeatureFlags.warnAboutDefaultPropsOnFunctionComponents = false; + ReactFeatureFlags.warnAboutStringRefs = false; }); it('should warn when given defaultProps', () => { @@ -35,13 +39,37 @@ describe('ReactDeprecationWarnings', () => { testProp: true, }; - expect(() => - ReactTestUtils.renderIntoDocument(), - ).toWarnDev( + ReactNoop.render(); + expect(() => expect(Scheduler).toFlushWithoutYielding()).toWarnDev( 'Warning: FunctionalComponent: Support for defaultProps ' + 'will be removed from function components in a future major ' + 'release. Use JavaScript default parameters instead.', {withoutStack: true}, ); }); + + it('should warn when given string refs', () => { + class RefComponent extends React.Component { + render() { + return null; + } + } + class Component extends React.Component { + render() { + return ; + } + } + + ReactNoop.render(); + expect(() => expect(Scheduler).toFlushWithoutYielding()).toWarnDev( + 'Warning: Component "Component" contains the string ref "refComponent". ' + + 'Support for string refs will be removed in a future major release. ' + + 'We recommend using useRef() or createRef() instead.' + + '\n\n' + + ' in Component (at **)' + + '\n\n' + + 'Learn more about using refs safely here:\n' + + 'https://fb.me/react-strict-mode-string-ref', + ); + }); }); diff --git a/packages/react-reconciler/src/ReactChildFiber.js b/packages/react-reconciler/src/ReactChildFiber.js index c0aeb7ccdd2..af113294a94 100644 --- a/packages/react-reconciler/src/ReactChildFiber.js +++ b/packages/react-reconciler/src/ReactChildFiber.js @@ -30,6 +30,7 @@ import { import invariant from 'shared/invariant'; import warning from 'shared/warning'; import warningWithoutStack from 'shared/warningWithoutStack'; +import {warnAboutStringRefs} from 'shared/ReactFeatureFlags'; import { createWorkInProgress, @@ -49,7 +50,7 @@ import {StrictMode} from './ReactTypeOfMode'; let didWarnAboutMaps; let didWarnAboutGenerators; -let didWarnAboutStringRefInStrictMode; +let didWarnAboutStringRefs; let ownerHasKeyUseWarning; let ownerHasFunctionTypeWarning; let warnForMissingKey = (child: mixed) => {}; @@ -57,7 +58,7 @@ let warnForMissingKey = (child: mixed) => {}; if (__DEV__) { didWarnAboutMaps = false; didWarnAboutGenerators = false; - didWarnAboutStringRefInStrictMode = {}; + didWarnAboutStringRefs = {}; /** * Warn if there's no key explicitly set on dynamic arrays of children or @@ -114,21 +115,38 @@ function coerceRef( typeof mixedRef !== 'object' ) { if (__DEV__) { - if (returnFiber.mode & StrictMode) { + // TODO: Clean this up once we turn on the string ref warning for + // everyone, because the strict mode case will no longer be relevant + if (returnFiber.mode & StrictMode || warnAboutStringRefs) { const componentName = getComponentName(returnFiber.type) || 'Component'; - if (!didWarnAboutStringRefInStrictMode[componentName]) { - warningWithoutStack( - false, - 'A string ref, "%s", has been found within a strict mode tree. ' + - 'String refs are a source of potential bugs and should be avoided. ' + - 'We recommend using createRef() instead.' + - '\n%s' + - '\n\nLearn more about using refs safely here:' + - '\nhttps://fb.me/react-strict-mode-string-ref', - mixedRef, - getStackByFiberInDevAndProd(returnFiber), - ); - didWarnAboutStringRefInStrictMode[componentName] = true; + if (!didWarnAboutStringRefs[componentName]) { + if (warnAboutStringRefs) { + warningWithoutStack( + false, + 'Component "%s" contains the string ref "%s". Support for string refs ' + + 'will be removed in a future major release. We recommend using ' + + 'useRef() or createRef() instead.' + + '\n%s' + + '\n\nLearn more about using refs safely here:' + + '\nhttps://fb.me/react-strict-mode-string-ref', + componentName, + mixedRef, + getStackByFiberInDevAndProd(returnFiber), + ); + } else { + warningWithoutStack( + false, + 'A string ref, "%s", has been found within a strict mode tree. ' + + 'String refs are a source of potential bugs and should be avoided. ' + + 'We recommend using useRef() or createRef() instead.' + + '\n%s' + + '\n\nLearn more about using refs safely here:' + + '\nhttps://fb.me/react-strict-mode-string-ref', + mixedRef, + getStackByFiberInDevAndProd(returnFiber), + ); + } + didWarnAboutStringRefs[componentName] = true; } } } diff --git a/packages/react/src/__tests__/ReactStrictMode-test.internal.js b/packages/react/src/__tests__/ReactStrictMode-test.internal.js index 5b6afee5581..b631690ffdb 100644 --- a/packages/react/src/__tests__/ReactStrictMode-test.internal.js +++ b/packages/react/src/__tests__/ReactStrictMode-test.internal.js @@ -693,7 +693,7 @@ Please update the following components: Parent`, }).toWarnDev( 'Warning: A string ref, "somestring", has been found within a strict mode tree. ' + 'String refs are a source of potential bugs and should be avoided. ' + - 'We recommend using createRef() instead.\n\n' + + 'We recommend using useRef() or createRef() instead.\n\n' + ' in StrictMode (at **)\n' + ' in OuterComponent (at **)\n\n' + 'Learn more about using refs safely here:\n' + @@ -735,7 +735,7 @@ Please update the following components: Parent`, }).toWarnDev( 'Warning: A string ref, "somestring", has been found within a strict mode tree. ' + 'String refs are a source of potential bugs and should be avoided. ' + - 'We recommend using createRef() instead.\n\n' + + 'We recommend using useRef() or createRef() instead.\n\n' + ' in InnerComponent (at **)\n' + ' in StrictMode (at **)\n' + ' in OuterComponent (at **)\n\n' + diff --git a/packages/shared/ReactFeatureFlags.js b/packages/shared/ReactFeatureFlags.js index da01edb1387..e7670b438e1 100644 --- a/packages/shared/ReactFeatureFlags.js +++ b/packages/shared/ReactFeatureFlags.js @@ -92,5 +92,6 @@ export const enableSuspenseCallback = false; // from React.createElement to React.jsx // https://github.com/reactjs/rfcs/blob/createlement-rfc/text/0000-create-element-changes.md export const warnAboutDefaultPropsOnFunctionComponents = false; +export const warnAboutStringRefs = false; export const disableLegacyContext = false; diff --git a/packages/shared/forks/ReactFeatureFlags.native-fb.js b/packages/shared/forks/ReactFeatureFlags.native-fb.js index 6b95b92d207..501eabf1e17 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-fb.js +++ b/packages/shared/forks/ReactFeatureFlags.native-fb.js @@ -40,6 +40,7 @@ export const flushSuspenseFallbacksInTests = true; export const enableUserBlockingEvents = false; export const enableSuspenseCallback = false; export const warnAboutDefaultPropsOnFunctionComponents = false; +export const warnAboutStringRefs = false; export const disableLegacyContext = false; // Only used in www builds. diff --git a/packages/shared/forks/ReactFeatureFlags.native-oss.js b/packages/shared/forks/ReactFeatureFlags.native-oss.js index 08525d0c093..f2fbda59acc 100644 --- a/packages/shared/forks/ReactFeatureFlags.native-oss.js +++ b/packages/shared/forks/ReactFeatureFlags.native-oss.js @@ -35,6 +35,7 @@ export const flushSuspenseFallbacksInTests = true; export const enableUserBlockingEvents = false; export const enableSuspenseCallback = false; export const warnAboutDefaultPropsOnFunctionComponents = false; +export const warnAboutStringRefs = false; export const disableLegacyContext = false; // Only used in www builds. diff --git a/packages/shared/forks/ReactFeatureFlags.persistent.js b/packages/shared/forks/ReactFeatureFlags.persistent.js index 478586ff80a..b3b3a1b5e8b 100644 --- a/packages/shared/forks/ReactFeatureFlags.persistent.js +++ b/packages/shared/forks/ReactFeatureFlags.persistent.js @@ -35,6 +35,7 @@ export const flushSuspenseFallbacksInTests = true; export const enableUserBlockingEvents = false; export const enableSuspenseCallback = false; export const warnAboutDefaultPropsOnFunctionComponents = false; +export const warnAboutStringRefs = false; export const disableLegacyContext = false; // Only used in www builds. diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.js index 91bfab22efa..2a874062ae7 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.js @@ -35,6 +35,7 @@ export const flushSuspenseFallbacksInTests = true; export const enableUserBlockingEvents = false; export const enableSuspenseCallback = false; export const warnAboutDefaultPropsOnFunctionComponents = false; +export const warnAboutStringRefs = false; export const disableLegacyContext = false; // Only used in www builds. diff --git a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js index 28f7d534292..eae97dc8882 100644 --- a/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js +++ b/packages/shared/forks/ReactFeatureFlags.test-renderer.www.js @@ -35,6 +35,7 @@ export const flushSuspenseFallbacksInTests = true; export const enableUserBlockingEvents = false; export const enableSuspenseCallback = true; export const warnAboutDefaultPropsOnFunctionComponents = false; +export const warnAboutStringRefs = false; export const disableLegacyContext = false; // Only used in www builds. diff --git a/packages/shared/forks/ReactFeatureFlags.www.js b/packages/shared/forks/ReactFeatureFlags.www.js index 3f2c4c6b519..a632bdcc8fc 100644 --- a/packages/shared/forks/ReactFeatureFlags.www.js +++ b/packages/shared/forks/ReactFeatureFlags.www.js @@ -81,6 +81,8 @@ export const enableSuspenseCallback = true; export const warnAboutDefaultPropsOnFunctionComponents = false; +export const warnAboutStringRefs = false; + export const flushSuspenseFallbacksInTests = true; // Flow magic to verify the exports of this file match the original version.