@@ -12,6 +12,7 @@ import type {ReactPortal} from 'shared/ReactTypes';
12
12
import type { Fiber } from 'react-reconciler/src/ReactFiber' ;
13
13
import type { ExpirationTime } from 'react-reconciler/src/ReactFiberExpirationTime' ;
14
14
15
+ import getComponentName from 'shared/getComponentName' ;
15
16
import { Placement , Deletion } from 'shared/ReactTypeOfSideEffect' ;
16
17
import {
17
18
getIteratorFn ,
@@ -26,6 +27,7 @@ import {
26
27
HostPortal ,
27
28
Fragment ,
28
29
} from 'shared/ReactTypeOfWork' ;
30
+ import { getStackAddendumByWorkInProgressFiber } from 'shared/ReactFiberComponentTreeHook' ;
29
31
import emptyObject from 'fbjs/lib/emptyObject' ;
30
32
import invariant from 'fbjs/lib/invariant' ;
31
33
import warning from 'fbjs/lib/warning' ;
@@ -38,16 +40,20 @@ import {
38
40
createFiberFromPortal ,
39
41
} from './ReactFiber' ;
40
42
import ReactDebugCurrentFiber from './ReactDebugCurrentFiber' ;
43
+ import { StrictMode } from './ReactTypeOfMode' ;
41
44
42
45
const { getCurrentFiberStackAddendum} = ReactDebugCurrentFiber ;
43
46
44
47
let didWarnAboutMaps ;
48
+ let didWarnAboutStringRefInStrictMode ;
45
49
let ownerHasKeyUseWarning ;
46
50
let ownerHasFunctionTypeWarning ;
47
51
let warnForMissingKey = ( child : mixed ) => { } ;
48
52
49
53
if ( __DEV__ ) {
50
54
didWarnAboutMaps = false ;
55
+ didWarnAboutStringRefInStrictMode = { } ;
56
+
51
57
/**
52
58
* Warn if there's no key explicitly set on dynamic arrays of children or
53
59
* object keys are not valid. This allows us to keep track of children between
@@ -92,13 +98,32 @@ if (__DEV__) {
92
98
93
99
const isArray = Array . isArray ;
94
100
95
- function coerceRef ( current : Fiber | null , element : ReactElement ) {
101
+ function coerceRef (
102
+ returnFiber : Fiber ,
103
+ current : Fiber | null ,
104
+ element : ReactElement ,
105
+ ) {
96
106
let mixedRef = element . ref ;
97
- if (
98
- mixedRef !== null &&
99
- typeof mixedRef !== 'function' &&
100
- typeof mixedRef !== 'object'
101
- ) {
107
+ if ( mixedRef !== null && typeof mixedRef !== 'function' && typeof mixedRef !== 'object' ) {
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 createRef() 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
+
102
127
if ( element . _owner ) {
103
128
const owner : ?Fiber = ( element . _owner : any ) ;
104
129
let inst ;
@@ -344,7 +369,7 @@ function ChildReconciler(shouldTrackSideEffects) {
344
369
if ( current !== null && current . type === element . type ) {
345
370
// Move based on index
346
371
const existing = useFiber ( current , element . props , expirationTime ) ;
347
- existing . ref = coerceRef ( current , element ) ;
372
+ existing . ref = coerceRef ( returnFiber , current , element ) ;
348
373
existing . return = returnFiber ;
349
374
if ( __DEV__ ) {
350
375
existing . _debugSource = element . _source ;
@@ -358,7 +383,7 @@ function ChildReconciler(shouldTrackSideEffects) {
358
383
returnFiber . mode ,
359
384
expirationTime ,
360
385
) ;
361
- created . ref = coerceRef ( current , element ) ;
386
+ created . ref = coerceRef ( returnFiber , current , element ) ;
362
387
created . return = returnFiber ;
363
388
return created ;
364
389
}
@@ -443,7 +468,7 @@ function ChildReconciler(shouldTrackSideEffects) {
443
468
returnFiber . mode ,
444
469
expirationTime ,
445
470
) ;
446
- created . ref = coerceRef ( null , newChild ) ;
471
+ created . ref = coerceRef ( returnFiber , null , newChild ) ;
447
472
created . return = returnFiber ;
448
473
return created ;
449
474
}
@@ -1081,7 +1106,7 @@ function ChildReconciler(shouldTrackSideEffects) {
1081
1106
: element . props ,
1082
1107
expirationTime ,
1083
1108
) ;
1084
- existing . ref = coerceRef ( child , element ) ;
1109
+ existing . ref = coerceRef ( returnFiber , child , element ) ;
1085
1110
existing . return = returnFiber ;
1086
1111
if ( __DEV__ ) {
1087
1112
existing . _debugSource = element . _source ;
@@ -1113,7 +1138,7 @@ function ChildReconciler(shouldTrackSideEffects) {
1113
1138
returnFiber . mode ,
1114
1139
expirationTime ,
1115
1140
) ;
1116
- created . ref = coerceRef ( currentFirstChild , element ) ;
1141
+ created . ref = coerceRef ( returnFiber , currentFirstChild , element ) ;
1117
1142
created . return = returnFiber ;
1118
1143
return created ;
1119
1144
}
0 commit comments