@@ -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,36 @@ 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
107
if (
98
108
mixedRef !== null &&
99
109
typeof mixedRef !== 'function' &&
100
110
typeof mixedRef !== 'object'
101
111
) {
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
+
102
131
if ( element . _owner ) {
103
132
const owner : ?Fiber = ( element . _owner : any ) ;
104
133
let inst ;
@@ -344,7 +373,7 @@ function ChildReconciler(shouldTrackSideEffects) {
344
373
if ( current !== null && current . type === element . type ) {
345
374
// Move based on index
346
375
const existing = useFiber ( current , element . props , expirationTime ) ;
347
- existing . ref = coerceRef ( current , element ) ;
376
+ existing . ref = coerceRef ( returnFiber , current , element ) ;
348
377
existing . return = returnFiber ;
349
378
if ( __DEV__ ) {
350
379
existing . _debugSource = element . _source ;
@@ -358,7 +387,7 @@ function ChildReconciler(shouldTrackSideEffects) {
358
387
returnFiber . mode ,
359
388
expirationTime ,
360
389
) ;
361
- created . ref = coerceRef ( current , element ) ;
390
+ created . ref = coerceRef ( returnFiber , current , element ) ;
362
391
created . return = returnFiber ;
363
392
return created ;
364
393
}
@@ -443,7 +472,7 @@ function ChildReconciler(shouldTrackSideEffects) {
443
472
returnFiber . mode ,
444
473
expirationTime ,
445
474
) ;
446
- created . ref = coerceRef ( null , newChild ) ;
475
+ created . ref = coerceRef ( returnFiber , null , newChild ) ;
447
476
created . return = returnFiber ;
448
477
return created ;
449
478
}
@@ -1081,7 +1110,7 @@ function ChildReconciler(shouldTrackSideEffects) {
1081
1110
: element . props ,
1082
1111
expirationTime ,
1083
1112
) ;
1084
- existing . ref = coerceRef ( child , element ) ;
1113
+ existing . ref = coerceRef ( returnFiber , child , element ) ;
1085
1114
existing . return = returnFiber ;
1086
1115
if ( __DEV__ ) {
1087
1116
existing . _debugSource = element . _source ;
@@ -1113,7 +1142,7 @@ function ChildReconciler(shouldTrackSideEffects) {
1113
1142
returnFiber . mode ,
1114
1143
expirationTime ,
1115
1144
) ;
1116
- created . ref = coerceRef ( currentFirstChild , element ) ;
1145
+ created . ref = coerceRef ( returnFiber , currentFirstChild , element ) ;
1117
1146
created . return = returnFiber ;
1118
1147
return created ;
1119
1148
}
0 commit comments