@@ -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,9 +98,32 @@ 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 ( mixedRef !== null && typeof mixedRef !== 'function' ) {
108+ if ( __DEV__ ) {
109+ if ( returnFiber . mode & StrictMode ) {
110+ const componentName = getComponentName ( returnFiber ) || 'Component' ;
111+ if ( ! didWarnAboutStringRefInStrictMode [ componentName ] ) {
112+ warning (
113+ false ,
114+ 'A string ref has been found within a strict mode tree. ' +
115+ 'String refs are a source of potential bugs and should be avoided. ' +
116+ 'We recommend using a ref callback instead.' +
117+ '\n%s' +
118+ '\n\nLearn more about using refs safely here:' +
119+ '\nhttps://fb.me/react-strict-mode-string-ref' ,
120+ getStackAddendumByWorkInProgressFiber ( returnFiber ) ,
121+ ) ;
122+ didWarnAboutStringRefInStrictMode [ componentName ] = true ;
123+ }
124+ }
125+ }
126+
98127 if ( element . _owner ) {
99128 const owner : ?Fiber = ( element . _owner : any ) ;
100129 let inst ;
@@ -340,7 +369,7 @@ function ChildReconciler(shouldTrackSideEffects) {
340369 if ( current !== null && current . type === element . type ) {
341370 // Move based on index
342371 const existing = useFiber ( current , element . props , expirationTime ) ;
343- existing . ref = coerceRef ( current , element ) ;
372+ existing . ref = coerceRef ( returnFiber , current , element ) ;
344373 existing . return = returnFiber ;
345374 if ( __DEV__ ) {
346375 existing . _debugSource = element . _source ;
@@ -354,7 +383,7 @@ function ChildReconciler(shouldTrackSideEffects) {
354383 returnFiber . mode ,
355384 expirationTime ,
356385 ) ;
357- created . ref = coerceRef ( current , element ) ;
386+ created . ref = coerceRef ( returnFiber , current , element ) ;
358387 created . return = returnFiber ;
359388 return created ;
360389 }
@@ -439,7 +468,7 @@ function ChildReconciler(shouldTrackSideEffects) {
439468 returnFiber . mode ,
440469 expirationTime ,
441470 ) ;
442- created . ref = coerceRef ( null , newChild ) ;
471+ created . ref = coerceRef ( returnFiber , null , newChild ) ;
443472 created . return = returnFiber ;
444473 return created ;
445474 }
@@ -1077,7 +1106,7 @@ function ChildReconciler(shouldTrackSideEffects) {
10771106 : element . props ,
10781107 expirationTime ,
10791108 ) ;
1080- existing . ref = coerceRef ( child , element ) ;
1109+ existing . ref = coerceRef ( returnFiber , child , element ) ;
10811110 existing . return = returnFiber ;
10821111 if ( __DEV__ ) {
10831112 existing . _debugSource = element . _source ;
@@ -1109,7 +1138,7 @@ function ChildReconciler(shouldTrackSideEffects) {
11091138 returnFiber . mode ,
11101139 expirationTime ,
11111140 ) ;
1112- created . ref = coerceRef ( currentFirstChild , element ) ;
1141+ created . ref = coerceRef ( returnFiber , currentFirstChild , element ) ;
11131142 created . return = returnFiber ;
11141143 return created ;
11151144 }
0 commit comments