@@ -12,6 +12,7 @@ import type {ReactPortal} from 'shared/ReactTypes';
1212import type { Fiber } from 'react-reconciler/src/ReactFiber' ;
1313import type { ExpirationTime } from 'react-reconciler/src/ReactFiberExpirationTime' ;
1414
15+ import getComponentName from 'shared/getComponentName' ;
1516import { Placement , Deletion } from 'shared/ReactTypeOfSideEffect' ;
1617import {
1718 getIteratorFn ,
@@ -26,6 +27,7 @@ import {
2627 HostPortal ,
2728 Fragment ,
2829} from 'shared/ReactTypeOfWork' ;
30+ import { getStackAddendumByWorkInProgressFiber } from 'shared/ReactFiberComponentTreeHook' ;
2931import emptyObject from 'fbjs/lib/emptyObject' ;
3032import invariant from 'fbjs/lib/invariant' ;
3133import warning from 'fbjs/lib/warning' ;
@@ -38,16 +40,20 @@ import {
3840 createFiberFromPortal ,
3941} from './ReactFiber' ;
4042import ReactDebugCurrentFiber from './ReactDebugCurrentFiber' ;
43+ import { StrictMode } from './ReactTypeOfMode' ;
4144
4245const { getCurrentFiberStackAddendum} = ReactDebugCurrentFiber ;
4346
4447let didWarnAboutMaps ;
48+ let didWarnAboutStringRefInStrictMode ;
4549let ownerHasKeyUseWarning ;
4650let ownerHasFunctionTypeWarning ;
4751let warnForMissingKey = ( child : mixed ) => { } ;
4852
4953if ( __DEV__ ) {
5054 didWarnAboutMaps = false ;
55+ didWarnAboutStringRefInStrictMode = { } ;
56+
5157 /**
5258 * Warn if there's no key explicitly set on dynamic arrays of children or
5359 * object keys are not valid. This allows us to keep track of children between
@@ -92,13 +98,36 @@ if (__DEV__) {
9298
9399const isArray = Array . isArray ;
94100
95- function coerceRef ( current : Fiber | null , element : ReactElement ) {
101+ function coerceRef (
102+ returnFiber : Fiber ,
103+ current : Fiber | null ,
104+ element : ReactElement ,
105+ ) {
96106 let mixedRef = element . ref ;
97107 if (
98108 mixedRef !== null &&
99109 typeof mixedRef !== 'function' &&
100110 typeof mixedRef !== 'object'
101111 ) {
112+ if ( __DEV__ ) {
113+ if ( returnFiber . mode & StrictMode ) {
114+ const componentName = getComponentName ( returnFiber ) || 'Component' ;
115+ if ( ! didWarnAboutStringRefInStrictMode [ componentName ] ) {
116+ warning (
117+ false ,
118+ 'A string ref has been found within a strict mode tree. ' +
119+ 'String refs are a source of potential bugs and should be avoided. ' +
120+ 'We recommend using createRef() instead.' +
121+ '\n%s' +
122+ '\n\nLearn more about using refs safely here:' +
123+ '\nhttps://fb.me/react-strict-mode-string-ref' ,
124+ getStackAddendumByWorkInProgressFiber ( returnFiber ) ,
125+ ) ;
126+ didWarnAboutStringRefInStrictMode [ componentName ] = true ;
127+ }
128+ }
129+ }
130+
102131 if ( element . _owner ) {
103132 const owner : ?Fiber = ( element . _owner : any ) ;
104133 let inst ;
@@ -344,7 +373,7 @@ function ChildReconciler(shouldTrackSideEffects) {
344373 if ( current !== null && current . type === element . type ) {
345374 // Move based on index
346375 const existing = useFiber ( current , element . props , expirationTime ) ;
347- existing . ref = coerceRef ( current , element ) ;
376+ existing . ref = coerceRef ( returnFiber , current , element ) ;
348377 existing . return = returnFiber ;
349378 if ( __DEV__ ) {
350379 existing . _debugSource = element . _source ;
@@ -358,7 +387,7 @@ function ChildReconciler(shouldTrackSideEffects) {
358387 returnFiber . mode ,
359388 expirationTime ,
360389 ) ;
361- created . ref = coerceRef ( current , element ) ;
390+ created . ref = coerceRef ( returnFiber , current , element ) ;
362391 created . return = returnFiber ;
363392 return created ;
364393 }
@@ -443,7 +472,7 @@ function ChildReconciler(shouldTrackSideEffects) {
443472 returnFiber . mode ,
444473 expirationTime ,
445474 ) ;
446- created . ref = coerceRef ( null , newChild ) ;
475+ created . ref = coerceRef ( returnFiber , null , newChild ) ;
447476 created . return = returnFiber ;
448477 return created ;
449478 }
@@ -1081,7 +1110,7 @@ function ChildReconciler(shouldTrackSideEffects) {
10811110 : element . props ,
10821111 expirationTime ,
10831112 ) ;
1084- existing . ref = coerceRef ( child , element ) ;
1113+ existing . ref = coerceRef ( returnFiber , child , element ) ;
10851114 existing . return = returnFiber ;
10861115 if ( __DEV__ ) {
10871116 existing . _debugSource = element . _source ;
@@ -1113,7 +1142,7 @@ function ChildReconciler(shouldTrackSideEffects) {
11131142 returnFiber . mode ,
11141143 expirationTime ,
11151144 ) ;
1116- created . ref = coerceRef ( currentFirstChild , element ) ;
1145+ created . ref = coerceRef ( returnFiber , currentFirstChild , element ) ;
11171146 created . return = returnFiber ;
11181147 return created ;
11191148 }
0 commit comments