Turn on string ref deprecation warning for everybody (not codemoddable) (#25383)
## Summary Alternate to https://github.com/facebook/react/pull/25334 without any prod runtime changes i.e. the proposed codemod in https://github.com/reactjs/rfcs/blob/createlement-rfc/text/0000-create-element-changes.md#deprecate-string-refs-and-remove-production-mode-_owner-field would not work. ## How did you test this change? - [x] CI - [x] `yarn test` with and without `warnAboutStringRefs`
Sebastian Silbermann committed
Nov 17, 2022 at 01:15 UTC
6fb8133ed3aa6b23063375dd345c6e413b05f0fe
37 files changed
+591
-300
packages/react-dom/src/__tests__/ReactComponent-test.js
+25
-4
@@ -12,6 +12,7 @@
12
let React;
13
let ReactDOM;
14
let ReactDOMServer;
15
+let ReactFeatureFlags;
16
let ReactTestUtils;
17
18
describe('ReactComponent', () => {
@@ -21,6 +22,7 @@ describe('ReactComponent', () => {
22
React = require('react');
23
ReactDOM = require('react-dom');
24
ReactDOMServer = require('react-dom/server');
25
+ ReactFeatureFlags = require('shared/ReactFeatureFlags');
26
ReactTestUtils = require('react-dom/test-utils');
27
});
28
@@ -36,7 +38,7 @@ describe('ReactComponent', () => {
38
}).toThrowError(/Target container is not a DOM element./);
39
});
40
39
- it('should throw when supplying a ref outside of render method', () => {
41
+ it('should throw when supplying a string ref outside of render method', () => {
42
let instance = <div ref="badDiv" />;
43
expect(function() {
44
instance = ReactTestUtils.renderIntoDocument(instance);
@@ -102,7 +104,7 @@ describe('ReactComponent', () => {
104
}
105
});
106
105
- it('should support refs on owned components', () => {
107
+ it('should support string refs on owned components', () => {
108
const innerObj = {};
109
const outerObj = {};
110
@@ -133,10 +135,29 @@ describe('ReactComponent', () => {
135
}
136
}
137
136
- ReactTestUtils.renderIntoDocument(<Component />);
138
+ expect(() => {
139
+ ReactTestUtils.renderIntoDocument(<Component />);
140
+ }).toErrorDev(
141
+ ReactFeatureFlags.warnAboutStringRefs
142
+ ? [
143
+ 'Warning: Component "div" contains the string ref "inner". ' +
144
+ 'Support for string refs will be removed in a future major release. ' +
145
+ 'We recommend using useRef() or createRef() instead. ' +
146
+ 'Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref\n' +
147
+ ' in div (at **)\n' +
148
+ ' in Wrapper (at **)\n' +
149
+ ' in Component (at **)',
150
+ 'Warning: Component "Component" contains the string ref "outer". ' +
151
+ 'Support for string refs will be removed in a future major release. ' +
152
+ 'We recommend using useRef() or createRef() instead. ' +
153
+ 'Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref\n' +
154
+ ' in Component (at **)',
155
+ ]
156
+ : [],
157
+ );
158
});
159
139
- it('should not have refs on unmounted components', () => {
160
+ it('should not have string refs on unmounted components', () => {
161
class Parent extends React.Component {
162
render() {
163
return (
packages/react-dom/src/__tests__/ReactComponentLifeCycle-test.js
+4
-2
@@ -378,7 +378,7 @@ describe('ReactComponentLifeCycle', () => {
378
}
379
// you would *NEVER* do anything like this in real code!
380
this.state.hasRenderCompleted = true;
381
- return <div ref="theDiv">I am the inner DIV</div>;
381
+ return <div ref={React.createRef()}>I am the inner DIV</div>;
382
}
383
384
componentWillUnmount() {
@@ -477,7 +477,9 @@ describe('ReactComponentLifeCycle', () => {
477
class Component extends React.Component {
478
render() {
479
return (
480
- <Tooltip ref="tooltip" tooltip={<div>{this.props.tooltipText}</div>}>
480
+ <Tooltip
481
+ ref={React.createRef()}
482
+ tooltip={<div>{this.props.tooltipText}</div>}>
483
{this.props.text}
484
</Tooltip>
485
);
packages/react-dom/src/__tests__/ReactCompositeComponent-test.js
+37
-26
@@ -72,6 +72,8 @@ describe('ReactCompositeComponent', () => {
72
MorphingComponent = class extends React.Component {
73
state = {activated: false};
74
75
+ xRef = React.createRef();
76
+
77
_toggleActivatedState = () => {
78
this.setState({activated: !this.state.activated});
79
};
@@ -79,9 +81,9 @@ describe('ReactCompositeComponent', () => {
81
render() {
82
const toggleActivatedState = this._toggleActivatedState;
83
return !this.state.activated ? (
82
- <a ref="x" onClick={toggleActivatedState} />
84
+ <a ref={this.xRef} onClick={toggleActivatedState} />
85
) : (
84
- <b ref="x" onClick={toggleActivatedState} />
86
+ <b ref={this.xRef} onClick={toggleActivatedState} />
87
);
88
}
89
};
@@ -91,14 +93,16 @@ describe('ReactCompositeComponent', () => {
93
* reallocated again.
94
*/
95
ChildUpdates = class extends React.Component {
96
+ anchorRef = React.createRef();
97
+
98
getAnchor = () => {
95
- return this.refs.anch;
99
+ return this.anchorRef.current;
100
};
101
102
render() {
103
const className = this.props.anchorClassOn ? 'anchorClass' : '';
104
return this.props.renderAnchor ? (
101
- <a ref="anch" className={className} />
105
+ <a ref={this.anchorRef} className={className} />
106
) : (
107
<b />
108
);
@@ -186,11 +190,11 @@ describe('ReactCompositeComponent', () => {
190
it('should rewire refs when rendering to different child types', () => {
191
const instance = ReactTestUtils.renderIntoDocument(<MorphingComponent />);
192
189
- expect(instance.refs.x.tagName).toBe('A');
193
+ expect(instance.xRef.current.tagName).toBe('A');
194
instance._toggleActivatedState();
191
- expect(instance.refs.x.tagName).toBe('B');
195
+ expect(instance.xRef.current.tagName).toBe('B');
196
instance._toggleActivatedState();
193
- expect(instance.refs.x.tagName).toBe('A');
197
+ expect(instance.xRef.current.tagName).toBe('A');
198
});
199
200
it('should not cache old DOM nodes when switching constructors', () => {
@@ -739,10 +743,13 @@ describe('ReactCompositeComponent', () => {
743
}
744
745
class Wrapper extends React.Component {
746
+ parentRef = React.createRef();
747
+ childRef = React.createRef();
748
+
749
render() {
750
return (
744
- <Parent ref="parent">
745
- <Child ref="child" />
751
+ <Parent ref={this.parentRef}>
752
+ <Child ref={this.childRef} />
753
</Parent>
754
);
755
}
@@ -750,14 +757,14 @@ describe('ReactCompositeComponent', () => {
757
758
const wrapper = ReactTestUtils.renderIntoDocument(<Wrapper />);
759
753
- expect(wrapper.refs.parent.state.flag).toEqual(true);
754
- expect(wrapper.refs.child.context).toEqual({flag: true});
760
+ expect(wrapper.parentRef.current.state.flag).toEqual(true);
761
+ expect(wrapper.childRef.current.context).toEqual({flag: true});
762
763
// We update <Parent /> while <Child /> is still a static prop relative to this update
757
- wrapper.refs.parent.setState({flag: false});
764
+ wrapper.parentRef.current.setState({flag: false});
765
759
- expect(wrapper.refs.parent.state.flag).toEqual(false);
760
- expect(wrapper.refs.child.context).toEqual({flag: false});
766
+ expect(wrapper.parentRef.current.state.flag).toEqual(false);
767
+ expect(wrapper.childRef.current.context).toEqual({flag: false});
768
});
769
770
it('should pass context transitively', () => {
@@ -1142,14 +1149,17 @@ describe('ReactCompositeComponent', () => {
1149
}
1150
1151
class Component extends React.Component {
1152
+ static0Ref = React.createRef();
1153
+ static1Ref = React.createRef();
1154
+
1155
render() {
1156
if (this.props.flipped) {
1157
return (
1158
<div>
1149
- <Static ref="static0" key="B">
1159
+ <Static ref={this.static0Ref} key="B">
1160
B (ignored)
1161
</Static>
1152
- <Static ref="static1" key="A">
1162
+ <Static ref={this.static1Ref} key="A">
1163
A (ignored)
1164
</Static>
1165
</div>
@@ -1157,10 +1167,10 @@ describe('ReactCompositeComponent', () => {
1167
} else {
1168
return (
1169
<div>
1160
- <Static ref="static0" key="A">
1170
+ <Static ref={this.static0Ref} key="A">
1171
A
1172
</Static>
1163
- <Static ref="static1" key="B">
1173
+ <Static ref={this.static1Ref} key="B">
1174
B
1175
</Static>
1176
</div>
@@ -1171,14 +1181,14 @@ describe('ReactCompositeComponent', () => {
1181
1182
const container = document.createElement('div');
1183
const comp = ReactDOM.render(<Component flipped={false} />, container);
1174
- expect(ReactDOM.findDOMNode(comp.refs.static0).textContent).toBe('A');
1175
- expect(ReactDOM.findDOMNode(comp.refs.static1).textContent).toBe('B');
1184
+ expect(ReactDOM.findDOMNode(comp.static0Ref.current).textContent).toBe('A');
1185
+ expect(ReactDOM.findDOMNode(comp.static1Ref.current).textContent).toBe('B');
1186
1187
// When flipping the order, the refs should update even though the actual
1188
// contents do not
1189
ReactDOM.render(<Component flipped={true} />, container);
1180
- expect(ReactDOM.findDOMNode(comp.refs.static0).textContent).toBe('B');
1181
- expect(ReactDOM.findDOMNode(comp.refs.static1).textContent).toBe('A');
1190
+ expect(ReactDOM.findDOMNode(comp.static0Ref.current).textContent).toBe('B');
1191
+ expect(ReactDOM.findDOMNode(comp.static1Ref.current).textContent).toBe('A');
1192
});
1193
1194
it('should allow access to findDOMNode in componentWillUnmount', () => {
@@ -1453,10 +1463,11 @@ describe('ReactCompositeComponent', () => {
1463
this.state = {
1464
color: 'green',
1465
};
1466
+ this.appleRef = React.createRef();
1467
}
1468
1469
render() {
1459
- return <Apple color={this.state.color} ref="apple" />;
1470
+ return <Apple color={this.state.color} ref={this.appleRef} />;
1471
}
1472
}
1473
@@ -1502,15 +1513,15 @@ describe('ReactCompositeComponent', () => {
1513
expect(renderCalls).toBe(2);
1514
1515
// Re-render base on state
1505
- instance.refs.apple.cut();
1516
+ instance.appleRef.current.cut();
1517
expect(renderCalls).toBe(3);
1518
1519
// No re-render based on state
1509
- instance.refs.apple.cut();
1520
+ instance.appleRef.current.cut();
1521
expect(renderCalls).toBe(3);
1522
1523
// Re-render based on state again
1513
- instance.refs.apple.eatSlice();
1524
+ instance.appleRef.current.eatSlice();
1525
expect(renderCalls).toBe(4);
1526
});
1527
packages/react-dom/src/__tests__/ReactDOMEventListener-test.js
+3
-2
@@ -193,12 +193,13 @@ describe('ReactDOMEventListener', () => {
193
const onMouseOut = event => mouseOut(event.target);
194
195
class Wrapper extends React.Component {
196
+ innerRef = React.createRef();
197
getInner = () => {
197
- return this.refs.inner;
198
+ return this.innerRef.current;
199
};
200
201
render() {
201
- const inner = <div ref="inner">Inner</div>;
202
+ const inner = <div ref={this.innerRef}>Inner</div>;
203
return (
204
<div>
205
<div onMouseOut={onMouseOut} id="outer">
packages/react-dom/src/__tests__/ReactDOMInput-test.js
+15
-6
@@ -1071,22 +1071,31 @@ describe('ReactDOMInput', () => {
1071
1072
it('should control radio buttons', () => {
1073
class RadioGroup extends React.Component {
1074
+ aRef = React.createRef();
1075
+ bRef = React.createRef();
1076
+ cRef = React.createRef();
1077
+
1078
render() {
1079
return (
1080
<div>
1081
<input
1078
- ref="a"
1082
+ ref={this.aRef}
1083
type="radio"
1084
name="fruit"
1085
checked={true}
1086
onChange={emptyFunction}
1087
/>
1088
A
1085
- <input ref="b" type="radio" name="fruit" onChange={emptyFunction} />
1089
+ <input
1090
+ ref={this.bRef}
1091
+ type="radio"
1092
+ name="fruit"
1093
+ onChange={emptyFunction}
1094
+ />
1095
B
1096
<form>
1097
<input
1089
- ref="c"
1098
+ ref={this.cRef}
1099
type="radio"
1100
name="fruit"
1101
defaultChecked={true}
@@ -1099,9 +1108,9 @@ describe('ReactDOMInput', () => {
1108
}
1109
1110
const stub = ReactDOM.render(<RadioGroup />, container);
1102
- const aNode = stub.refs.a;
1103
- const bNode = stub.refs.b;
1104
- const cNode = stub.refs.c;
1111
+ const aNode = stub.aRef.current;
1112
+ const bNode = stub.bRef.current;
1113
+ const cNode = stub.cRef.current;
1114
1115
expect(aNode.checked).toBe(true);
1116
expect(bNode.checked).toBe(false);
packages/react-dom/src/__tests__/ReactDOMServerIntegrationAttributes-test.js
+1
-1
@@ -337,7 +337,7 @@ describe('ReactDOMServerIntegration', () => {
337
itRenders('no ref attribute', async render => {
338
class RefComponent extends React.Component {
339
render() {
340
- return <div ref="foo" />;
340
+ return <div ref={React.createRef()} />;
341
}
342
}
343
const e = await render(<RefComponent />);
packages/react-dom/src/__tests__/ReactDOMServerIntegrationRefs-test.js
+18
-4
@@ -14,6 +14,7 @@ const ReactDOMServerIntegrationUtils = require('./utils/ReactDOMServerIntegratio
14
let React;
15
let ReactDOM;
16
let ReactDOMServer;
17
+let ReactFeatureFlags;
18
let ReactTestUtils;
19
20
function initModules() {
@@ -22,6 +23,7 @@ function initModules() {
23
React = require('react');
24
ReactDOM = require('react-dom');
25
ReactDOMServer = require('react-dom/server');
26
+ ReactFeatureFlags = require('shared/ReactFeatureFlags');
27
ReactTestUtils = require('react-dom/test-utils');
28
29
// Make them available to the helpers.
@@ -91,10 +93,22 @@ describe('ReactDOMServerIntegration', () => {
93
root.innerHTML = markup;
94
let component = null;
95
resetModules();
94
- await asyncReactDOMRender(
95
- <RefsComponent ref={e => (component = e)} />,
96
- root,
97
- true,
96
+ await expect(async () => {
97
+ await asyncReactDOMRender(
98
+ <RefsComponent ref={e => (component = e)} />,
99
+ root,
100
+ true,
101
+ );
102
+ }).toErrorDev(
103
+ ReactFeatureFlags.warnAboutStringRefs
104
+ ? [
105
+ 'Warning: Component "RefsComponent" contains the string ref "myDiv". ' +
106
+ 'Support for string refs will be removed in a future major release. ' +
107
+ 'We recommend using useRef() or createRef() instead. ' +
108
+ 'Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref\n' +
109
+ ' in RefsComponent (at **)',
110
+ ]
111
+ : [],
112
);
113
expect(component.refs.myDiv).toBe(root.firstChild);
114
});
packages/react-dom/src/__tests__/ReactIdentity-test.js
+3
-2
@@ -67,17 +67,18 @@ describe('ReactIdentity', () => {
67
68
function renderAComponentWithKeyIntoContainer(key, container) {
69
class Wrapper extends React.Component {
70
+ spanRef = React.createRef();
71
render() {
72
return (
73
<div>
73
- <span ref="span" key={key} />
74
+ <span ref={this.spanRef} key={key} />
75
</div>
76
);
77
}
78
}
79
80
const instance = ReactDOM.render(<Wrapper />, container);
80
- const span = instance.refs.span;
81
+ const span = instance.spanRef.current;
82
expect(span).not.toBe(null);
83
}
84
packages/react-dom/src/__tests__/ReactMultiChildReconcile-test.js
+7
-3
@@ -60,6 +60,8 @@ class StatusDisplay extends React.Component {
60
* Displays friends statuses.
61
*/
62
class FriendsStatusDisplay extends React.Component {
63
+ displays = {};
64
+
65
/**
66
* Gets the order directly from each rendered child's `index` field.
67
* Refs are not maintained in the rendered order, and neither is
@@ -84,7 +86,7 @@ class FriendsStatusDisplay extends React.Component {
86
const originalKeys = this.getOriginalKeys();
87
for (let i = 0; i < originalKeys.length; i++) {
88
const key = originalKeys[i];
87
- res[key] = this.refs[key];
89
+ res[key] = this.displays[key];
90
}
91
return res;
92
}
@@ -104,7 +106,7 @@ class FriendsStatusDisplay extends React.Component {
106
// We are only interested in children up to the current key.
107
return;
108
}
107
- expect(this.refs[key]).toBeTruthy();
109
+ expect(this.displays[key]).toBeTruthy();
110
}
111
}
112
@@ -116,7 +118,9 @@ class FriendsStatusDisplay extends React.Component {
118
!status ? null : (
119
<StatusDisplay
120
key={key}
119
- ref={key}
121
+ ref={current => {
122
+ this.displays[key] = current;
123
+ }}
124
contentKey={key}
125
onFlush={this.verifyPreviousRefsResolved.bind(this, key)}
126
status={status}
packages/react-dom/src/__tests__/ReactServerRenderingHydration-test.js
+5
-3
@@ -36,6 +36,8 @@ describe('ReactDOMServerHydration', () => {
36
let numClicks = 0;
37
38
class TestComponent extends React.Component {
39
+ spanRef = React.createRef();
40
+
41
componentDidMount() {
42
mountCount++;
43
}
@@ -46,7 +48,7 @@ describe('ReactDOMServerHydration', () => {
48
49
render() {
50
return (
49
- <span ref="span" onClick={this.click}>
51
+ <span ref={this.spanRef} onClick={this.click}>
52
Name: {this.props.name}
53
</span>
54
);
@@ -89,7 +91,7 @@ describe('ReactDOMServerHydration', () => {
91
92
// Ensure the events system works after mount into server markup
93
expect(numClicks).toEqual(0);
92
- instance.refs.span.click();
94
+ instance.spanRef.current.click();
95
expect(numClicks).toEqual(1);
96
97
ReactDOM.unmountComponentAtNode(element);
@@ -107,7 +109,7 @@ describe('ReactDOMServerHydration', () => {
109
110
// Ensure the events system works after markup mismatch.
111
expect(numClicks).toEqual(1);
110
- instance.refs.span.click();
112
+ instance.spanRef.current.click();
113
expect(numClicks).toEqual(2);
114
} finally {
115
document.body.removeChild(element);
packages/react-dom/src/__tests__/ReactTestUtils-test.js
+16
-11
@@ -221,13 +221,17 @@ describe('ReactTestUtils', () => {
221
// Full-page components (html, head, body) can't be rendered into a div
222
// directly...
223
class Root extends React.Component {
224
+ htmlRef = React.createRef();
225
+ headRef = React.createRef();
226
+ bodyRef = React.createRef();
227
+
228
render() {
229
return (
226
- <html ref="html">
227
- <head ref="head">
230
+ <html ref={this.htmlRef}>
231
+ <head ref={this.headRef}>
232
<title>hello</title>
233
</head>
230
- <body ref="body">hello, world</body>
234
+ <body ref={this.bodyRef}>hello, world</body>
235
</html>
236
);
237
}
@@ -237,12 +241,12 @@ describe('ReactTestUtils', () => {
241
const testDocument = getTestDocument(markup);
242
const component = ReactDOM.hydrate(<Root />, testDocument);
243
240
- expect(component.refs.html.tagName).toBe('HTML');
241
- expect(component.refs.head.tagName).toBe('HEAD');
242
- expect(component.refs.body.tagName).toBe('BODY');
243
- expect(ReactTestUtils.isDOMComponent(component.refs.html)).toBe(true);
244
- expect(ReactTestUtils.isDOMComponent(component.refs.head)).toBe(true);
245
- expect(ReactTestUtils.isDOMComponent(component.refs.body)).toBe(true);
244
+ expect(component.htmlRef.current.tagName).toBe('HTML');
245
+ expect(component.headRef.current.tagName).toBe('HEAD');
246
+ expect(component.bodyRef.current.tagName).toBe('BODY');
247
+ expect(ReactTestUtils.isDOMComponent(component.htmlRef.current)).toBe(true);
248
+ expect(ReactTestUtils.isDOMComponent(component.headRef.current)).toBe(true);
249
+ expect(ReactTestUtils.isDOMComponent(component.bodyRef.current)).toBe(true);
250
});
251
252
it('can scry with stateless components involved', () => {
@@ -348,12 +352,13 @@ describe('ReactTestUtils', () => {
352
353
it('should change the value of an input field in a component', () => {
354
class SomeComponent extends React.Component {
355
+ inputRef = React.createRef();
356
render() {
357
return (
358
<div>
359
<input
360
type="text"
356
- ref="input"
361
+ ref={this.inputRef}
362
onChange={this.props.handleChange}
363
/>
364
</div>
@@ -373,7 +378,7 @@ describe('ReactTestUtils', () => {
378
container,
379
);
380
376
- const node = instance.refs.input;
381
+ const node = instance.inputRef.current;
382
node.value = 'zebra';
383
ReactTestUtils.Simulate.change(node);
384
packages/react-dom/src/__tests__/ReactUpdates-test.js
+35
-19
@@ -147,6 +147,7 @@ describe('ReactUpdates', () => {
147
148
class Parent extends React.Component {
149
state = {x: 0};
150
+ childRef = React.createRef();
151
152
componentDidUpdate() {
153
parentUpdateCount++;
@@ -155,7 +156,7 @@ describe('ReactUpdates', () => {
156
render() {
157
return (
158
<div>
158
- <Child ref="child" x={this.state.x} />
159
+ <Child ref={this.childRef} x={this.state.x} />
160
</div>
161
);
162
}
@@ -176,7 +177,7 @@ describe('ReactUpdates', () => {
177
}
178
179
const instance = ReactTestUtils.renderIntoDocument(<Parent />);
179
- const child = instance.refs.child;
180
+ const child = instance.childRef.current;
181
expect(instance.state.x).toBe(0);
182
expect(child.state.y).toBe(0);
183
@@ -200,6 +201,7 @@ describe('ReactUpdates', () => {
201
202
class Parent extends React.Component {
203
state = {x: 0};
204
+ childRef = React.createRef();
205
206
componentDidUpdate() {
207
parentUpdateCount++;
@@ -208,7 +210,7 @@ describe('ReactUpdates', () => {
210
render() {
211
return (
212
<div>
211
- <Child ref="child" x={this.state.x} />
213
+ <Child ref={this.childRef} x={this.state.x} />
214
</div>
215
);
216
}
@@ -229,7 +231,7 @@ describe('ReactUpdates', () => {
231
}
232
233
const instance = ReactTestUtils.renderIntoDocument(<Parent />);
232
- const child = instance.refs.child;
234
+ const child = instance.childRef.current;
235
expect(instance.state.x).toBe(0);
236
expect(child.state.y).toBe(0);
237
@@ -336,13 +338,15 @@ describe('ReactUpdates', () => {
338
let childRenderCount = 0;
339
340
class Parent extends React.Component {
341
+ childRef = React.createRef();
342
+
343
shouldComponentUpdate() {
344
return false;
345
}
346
347
render() {
348
parentRenderCount++;
345
- return <Child ref="child" />;
349
+ return <Child ref={this.childRef} />;
350
}
351
}
352
@@ -370,7 +374,7 @@ describe('ReactUpdates', () => {
374
expect(childRenderCount).toBe(1);
375
376
ReactDOM.unstable_batchedUpdates(function() {
373
- instance.refs.child.setState({x: 1});
377
+ instance.childRef.current.setState({x: 1});
378
});
379
380
expect(parentRenderCount).toBe(1);
@@ -428,28 +432,34 @@ describe('ReactUpdates', () => {
432
};
433
434
class Box extends React.Component {
435
+ boxDivRef = React.createRef();
436
+
437
render() {
432
- return <div ref="boxDiv">{this.props.children}</div>;
438
+ return <div ref={this.boxDivRef}>{this.props.children}</div>;
439
}
440
}
441
Object.assign(Box.prototype, UpdateLoggingMixin);
442
443
class Child extends React.Component {
444
+ spanRef = React.createRef();
445
+
446
render() {
439
- return <span ref="span">child</span>;
447
+ return <span ref={this.spanRef}>child</span>;
448
}
449
}
450
Object.assign(Child.prototype, UpdateLoggingMixin);
451
452
class Switcher extends React.Component {
453
state = {tabKey: 'hello'};
454
+ boxRef = React.createRef();
455
+ switcherDivRef = React.createRef();
456
render() {
457
const child = this.props.children;
458
459
return (
450
- <Box ref="box">
460
+ <Box ref={this.boxRef}>
461
<div
452
- ref="switcherDiv"
462
+ ref={this.switcherDivRef}
463
style={{
464
display: this.state.tabKey === child.key ? '' : 'none',
465
}}>
@@ -462,10 +472,13 @@ describe('ReactUpdates', () => {
472
Object.assign(Switcher.prototype, UpdateLoggingMixin);
473
474
class App extends React.Component {
475
+ switcherRef = React.createRef();
476
+ childRef = React.createRef();
477
+
478
render() {
479
return (
467
- <Switcher ref="switcher">
468
- <Child key="hello" ref="child" />
480
+ <Switcher ref={this.switcherRef}>
481
+ <Child key="hello" ref={this.childRef} />
482
</Switcher>
483
);
484
}
@@ -513,21 +526,21 @@ describe('ReactUpdates', () => {
526
expectUpdates(desiredWillUpdates, desiredDidUpdates);
527
}
528
testUpdates(
516
- [root.refs.switcher.refs.box, root.refs.switcher],
529
+ [root.switcherRef.current.boxRef.current, root.switcherRef.current],
530
// Owner-child relationships have inverse will and did
531
['Switcher', 'Box'],
532
['Box', 'Switcher'],
533
);
534
535
testUpdates(
523
- [root.refs.child, root.refs.switcher.refs.box],
536
+ [root.childRef.current, root.switcherRef.current.boxRef.current],
537
// Not owner-child so reconcile independently
538
['Box', 'Child'],
539
['Box', 'Child'],
540
);
541
542
testUpdates(
530
- [root.refs.child, root.refs.switcher],
543
+ [root.childRef.current, root.switcherRef.current],
544
// Switcher owns Box and Child, Box does not own Child
545
['Switcher', 'Box', 'Child'],
546
['Box', 'Switcher', 'Child'],
@@ -588,12 +601,13 @@ describe('ReactUpdates', () => {
601
602
class Outer extends React.Component {
603
state = {x: 0};
604
+ innerRef = React.createRef();
605
606
render() {
607
updates.push('Outer-render-' + this.state.x);
608
return (
609
<div>
596
- <Inner x={this.state.x} ref="inner" />
610
+ <Inner x={this.state.x} ref={this.innerRef} />
611
</div>
612
);
613
}
@@ -602,7 +616,7 @@ describe('ReactUpdates', () => {
616
const x = this.state.x;
617
updates.push('Outer-didUpdate-' + x);
618
updates.push('Inner-setState-' + x);
605
- this.refs.inner.setState({x: x}, function() {
619
+ this.innerRef.current.setState({x: x}, function() {
620
updates.push('Inner-callback-' + x);
621
});
622
}
@@ -945,12 +959,14 @@ describe('ReactUpdates', () => {
959
960
it('does not update one component twice in a batch (#2410)', () => {
961
class Parent extends React.Component {
962
+ childRef = React.createRef();
963
+
964
getChild = () => {
949
- return this.refs.child;
965
+ return this.childRef.current;
966
};
967
968
render() {
953
- return <Child ref="child" />;
969
+ return <Child ref={this.childRef} />;
970
}
971
}
972
packages/react-dom/src/__tests__/refs-destruction-test.js
+29
-33
@@ -30,6 +30,9 @@ describe('refs-destruction', () => {
30
}
31
32
TestComponent = class extends React.Component {
33
+ theInnerDivRef = React.createRef();
34
+ theInnerClassComponentRef = React.createRef();
35
+
36
render() {
37
if (this.props.destroy) {
38
return <div />;
@@ -43,8 +46,8 @@ describe('refs-destruction', () => {
46
} else {
47
return (
48
<div>
46
- <div ref="theInnerDiv" />
47
- <ClassComponent ref="theInnerClassComponent" />
49
+ <div ref={this.theInnerDivRef} />
50
+ <ClassComponent ref={this.theInnerClassComponentRef} />
51
</div>
52
);
53
}
@@ -55,52 +58,45 @@ describe('refs-destruction', () => {
58
it('should remove refs when destroying the parent', () => {
59
const container = document.createElement('div');
60
const testInstance = ReactDOM.render(<TestComponent />, container);
58
- expect(ReactTestUtils.isDOMComponent(testInstance.refs.theInnerDiv)).toBe(
59
- true,
60
- );
61
+
62
expect(
62
- Object.keys(testInstance.refs || {}).filter(key => testInstance.refs[key])
63
- .length,
64
- ).toEqual(2);
63
+ ReactTestUtils.isDOMComponent(testInstance.theInnerDivRef.current),
64
+ ).toBe(true);
65
+ expect(testInstance.theInnerClassComponentRef.current).toBeTruthy();
66
+
67
ReactDOM.unmountComponentAtNode(container);
66
- expect(
67
- Object.keys(testInstance.refs || {}).filter(key => testInstance.refs[key])
68
- .length,
69
- ).toEqual(0);
68
+
69
+ expect(testInstance.theInnerDivRef.current).toBe(null);
70
+ expect(testInstance.theInnerClassComponentRef.current).toBe(null);
71
});
72
73
it('should remove refs when destroying the child', () => {
74
const container = document.createElement('div');
75
const testInstance = ReactDOM.render(<TestComponent />, container);
75
- expect(ReactTestUtils.isDOMComponent(testInstance.refs.theInnerDiv)).toBe(
76
- true,
77
- );
76
expect(
79
- Object.keys(testInstance.refs || {}).filter(key => testInstance.refs[key])
80
- .length,
81
- ).toEqual(2);
77
+ ReactTestUtils.isDOMComponent(testInstance.theInnerDivRef.current),
78
+ ).toBe(true);
79
+ expect(testInstance.theInnerClassComponentRef.current).toBeTruthy();
80
+
81
ReactDOM.render(<TestComponent destroy={true} />, container);
83
- expect(
84
- Object.keys(testInstance.refs || {}).filter(key => testInstance.refs[key])
85
- .length,
86
- ).toEqual(0);
82
+
83
+ expect(testInstance.theInnerDivRef.current).toBe(null);
84
+ expect(testInstance.theInnerClassComponentRef.current).toBe(null);
85
});
86
87
it('should remove refs when removing the child ref attribute', () => {
88
const container = document.createElement('div');
89
const testInstance = ReactDOM.render(<TestComponent />, container);
92
- expect(ReactTestUtils.isDOMComponent(testInstance.refs.theInnerDiv)).toBe(
93
- true,
94
- );
90
+
91
expect(
96
- Object.keys(testInstance.refs || {}).filter(key => testInstance.refs[key])
97
- .length,
98
- ).toEqual(2);
92
+ ReactTestUtils.isDOMComponent(testInstance.theInnerDivRef.current),
93
+ ).toBe(true);
94
+ expect(testInstance.theInnerClassComponentRef.current).toBeTruthy();
95
+
96
ReactDOM.render(<TestComponent removeRef={true} />, container);
100
- expect(
101
- Object.keys(testInstance.refs || {}).filter(key => testInstance.refs[key])
102
- .length,
103
- ).toEqual(0);
97
+
98
+ expect(testInstance.theInnerDivRef.current).toBe(null);
99
+ expect(testInstance.theInnerClassComponentRef.current).toBe(null);
100
});
101
102
it('should not error when destroying child with ref asynchronously', () => {
@@ -135,7 +131,7 @@ describe('refs-destruction', () => {
131
render() {
132
return (
133
<Modal>
138
- <a ref="ref" />
134
+ <a ref={React.createRef()} />
135
</Modal>
136
);
137
}
packages/react-dom/src/__tests__/refs-test.js
+180
-102
@@ -11,86 +11,12 @@
11
12
let React = require('react');
13
let ReactDOM = require('react-dom');
14
+let ReactFeatureFlags = require('shared/ReactFeatureFlags');
15
let ReactTestUtils = require('react-dom/test-utils');
16
16
-/**
17
- * Counts clicks and has a renders an item for each click. Each item rendered
18
- * has a ref of the form "clickLogN".
19
- */
20
-class ClickCounter extends React.Component {
21
- state = {count: this.props.initialCount};
22
-
23
- triggerReset = () => {
24
- this.setState({count: this.props.initialCount});
25
- };
26
-
27
- handleClick = () => {
28
- this.setState({count: this.state.count + 1});
29
- };
30
-
31
- render() {
32
- const children = [];
33
- let i;
34
- for (i = 0; i < this.state.count; i++) {
35
- children.push(
36
- <div
37
- className="clickLogDiv"
38
- key={'clickLog' + i}
39
- ref={'clickLog' + i}
40
- />,
41
- );
42
- }
43
- return (
44
- <span className="clickIncrementer" onClick={this.handleClick}>
45
- {children}
46
- </span>
47
- );
48
- }
49
-}
50
-
51
-/**
52
- * Only purpose is to test that refs are tracked even when applied to a
53
- * component that is injected down several layers. Ref systems are difficult to
54
- * build in such a way that ownership is maintained in an airtight manner.
55
- */
56
-class GeneralContainerComponent extends React.Component {
57
- render() {
58
- return <div>{this.props.children}</div>;
59
- }
60
-}
61
-
62
-/**
63
- * Notice how refs ownership is maintained even when injecting a component
64
- * into a different parent.
65
- */
66
-class TestRefsComponent extends React.Component {
67
- doReset = () => {
68
- this.refs.myCounter.triggerReset();
69
- };
70
-
71
- render() {
72
- return (
73
- <div>
74
- <div ref="resetDiv" onClick={this.doReset}>
75
- Reset Me By Clicking This.
76
- </div>
77
- <GeneralContainerComponent ref="myContainer">
78
- <ClickCounter ref="myCounter" initialCount={1} />
79
- </GeneralContainerComponent>
80
- </div>
81
- );
82
- }
83
-}
84
-
85
-const expectClickLogsLengthToBe = function(instance, length) {
86
- const clickLogs = ReactTestUtils.scryRenderedDOMComponentsWithClass(
87
- instance,
88
- 'clickLogDiv',
89
- );
90
- expect(clickLogs.length).toBe(length);
91
- expect(Object.keys(instance.refs.myCounter.refs).length).toBe(length);
92
-};
93
-
17
+// This is testing if string refs are deleted from `instance.refs`
18
+// Once support for string refs is removed, this test can be removed.
19
+// Detaching is already tested in refs-detruction-test.js
20
describe('reactiverefs', () => {
21
let container;
22
@@ -98,6 +24,7 @@ describe('reactiverefs', () => {
24
jest.resetModules();
25
React = require('react');
26
ReactDOM = require('react-dom');
27
+ ReactFeatureFlags = require('shared/ReactFeatureFlags');
28
ReactTestUtils = require('react-dom/test-utils');
29
});
30
@@ -108,13 +35,117 @@ describe('reactiverefs', () => {
35
}
36
});
37
38
+ /**
39
+ * Counts clicks and has a renders an item for each click. Each item rendered
40
+ * has a ref of the form "clickLogN".
41
+ */
42
+ class ClickCounter extends React.Component {
43
+ state = {count: this.props.initialCount};
44
+
45
+ triggerReset = () => {
46
+ this.setState({count: this.props.initialCount});
47
+ };
48
+
49
+ handleClick = () => {
50
+ this.setState({count: this.state.count + 1});
51
+ };
52
+
53
+ render() {
54
+ const children = [];
55
+ let i;
56
+ for (i = 0; i < this.state.count; i++) {
57
+ children.push(
58
+ <div
59
+ className="clickLogDiv"
60
+ key={'clickLog' + i}
61
+ ref={'clickLog' + i}
62
+ />,
63
+ );
64
+ }
65
+ return (
66
+ <span className="clickIncrementer" onClick={this.handleClick}>
67
+ {children}
68
+ </span>
69
+ );
70
+ }
71
+ }
72
+
73
+ const expectClickLogsLengthToBe = function(instance, length) {
74
+ const clickLogs = ReactTestUtils.scryRenderedDOMComponentsWithClass(
75
+ instance,
76
+ 'clickLogDiv',
77
+ );
78
+ expect(clickLogs.length).toBe(length);
79
+ expect(Object.keys(instance.refs.myCounter.refs).length).toBe(length);
80
+ };
81
+
82
/**
83
* Render a TestRefsComponent and ensure that the main refs are wired up.
84
*/
85
const renderTestRefsComponent = function() {
86
+ /**
87
+ * Only purpose is to test that refs are tracked even when applied to a
88
+ * component that is injected down several layers. Ref systems are difficult to
89
+ * build in such a way that ownership is maintained in an airtight manner.
90
+ */
91
+ class GeneralContainerComponent extends React.Component {
92
+ render() {
93
+ return <div>{this.props.children}</div>;
94
+ }
95
+ }
96
+
97
+ /**
98
+ * Notice how refs ownership is maintained even when injecting a component
99
+ * into a different parent.
100
+ */
101
+ class TestRefsComponent extends React.Component {
102
+ doReset = () => {
103
+ this.refs.myCounter.triggerReset();
104
+ };
105
+
106
+ render() {
107
+ return (
108
+ <div>
109
+ <div ref="resetDiv" onClick={this.doReset}>
110
+ Reset Me By Clicking This.
111
+ </div>
112
+ <GeneralContainerComponent ref="myContainer">
113
+ <ClickCounter ref="myCounter" initialCount={1} />
114
+ </GeneralContainerComponent>
115
+ </div>
116
+ );
117
+ }
118
+ }
119
+
120
container = document.createElement('div');
121
document.body.appendChild(container);
117
- const testRefsComponent = ReactDOM.render(<TestRefsComponent />, container);
122
+
123
+ let testRefsComponent;
124
+ expect(() => {
125
+ testRefsComponent = ReactDOM.render(<TestRefsComponent />, container);
126
+ }).toErrorDev(
127
+ ReactFeatureFlags.warnAboutStringRefs
128
+ ? [
129
+ 'Warning: Component "div" contains the string ref "resetDiv". ' +
130
+ 'Support for string refs will be removed in a future major release. ' +
131
+ 'We recommend using useRef() or createRef() instead. ' +
132
+ 'Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref\n' +
133
+ ' in div (at **)\n' +
134
+ ' in TestRefsComponent (at **)',
135
+ 'Warning: Component "span" contains the string ref "clickLog0". ' +
136
+ 'Support for string refs will be removed in a future major release. ' +
137
+ 'We recommend using useRef() or createRef() instead. ' +
138
+ 'Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref\n' +
139
+ ' in span (at **)\n' +
140
+ ' in ClickCounter (at **)\n' +
141
+ ' in div (at **)\n' +
142
+ ' in GeneralContainerComponent (at **)\n' +
143
+ ' in div (at **)\n' +
144
+ ' in TestRefsComponent (at **)',
145
+ ]
146
+ : [],
147
+ );
148
+
149
expect(testRefsComponent instanceof TestRefsComponent).toBe(true);
150
151
const generalContainer = testRefsComponent.refs.myContainer;
@@ -156,13 +187,14 @@ describe('reactiverefs', () => {
187
});
188
});
189
159
-if (!require('shared/ReactFeatureFlags').disableModulePatternComponents) {
190
+if (!ReactFeatureFlags.disableModulePatternComponents) {
191
describe('factory components', () => {
192
it('Should correctly get the ref', () => {
193
function Comp() {
194
return {
195
+ elemRef: React.createRef(),
196
render() {
165
- return <div ref="elemRef" />;
197
+ return <div ref={this.elemRef} />;
198
},
199
};
200
}
@@ -177,7 +209,7 @@ if (!require('shared/ReactFeatureFlags').disableModulePatternComponents) {
209
'`Comp.prototype = React.Component.prototype`. ' +
210
"Don't use an arrow function since it cannot be called with `new` by React.",
211
);
180
- expect(inst.refs.elemRef.tagName).toBe('DIV');
212
+ expect(inst.elemRef.current.tagName).toBe('DIV');
213
});
214
});
215
}
@@ -191,10 +223,15 @@ describe('ref swapping', () => {
223
jest.resetModules();
224
React = require('react');
225
ReactDOM = require('react-dom');
226
+ ReactFeatureFlags = require('shared/ReactFeatureFlags');
227
ReactTestUtils = require('react-dom/test-utils');
228
229
RefHopsAround = class extends React.Component {
230
state = {count: 0};
231
+ hopRef = React.createRef();
232
+ divOneRef = React.createRef();
233
+ divTwoRef = React.createRef();
234
+ divThreeRef = React.createRef();
235
236
moveRef = () => {
237
this.setState({count: this.state.count + 1});
@@ -212,15 +249,15 @@ describe('ref swapping', () => {
249
<div>
250
<div
251
className="first"
215
- ref={count % 3 === 0 ? 'hopRef' : 'divOneRef'}
252
+ ref={count % 3 === 0 ? this.hopRef : this.divOneRef}
253
/>
254
<div
255
className="second"
219
- ref={count % 3 === 1 ? 'hopRef' : 'divTwoRef'}
256
+ ref={count % 3 === 1 ? this.hopRef : this.divTwoRef}
257
/>
258
<div
259
className="third"
223
- ref={count % 3 === 2 ? 'hopRef' : 'divThreeRef'}
260
+ ref={count % 3 === 2 ? this.hopRef : this.divThreeRef}
261
/>
262
</div>
263
);
@@ -244,28 +281,28 @@ describe('ref swapping', () => {
281
'third',
282
);
283
247
- expect(refHopsAround.refs.hopRef).toEqual(firstDiv);
248
- expect(refHopsAround.refs.divTwoRef).toEqual(secondDiv);
249
- expect(refHopsAround.refs.divThreeRef).toEqual(thirdDiv);
284
+ expect(refHopsAround.hopRef.current).toEqual(firstDiv);
285
+ expect(refHopsAround.divTwoRef.current).toEqual(secondDiv);
286
+ expect(refHopsAround.divThreeRef.current).toEqual(thirdDiv);
287
288
refHopsAround.moveRef();
252
- expect(refHopsAround.refs.divOneRef).toEqual(firstDiv);
253
- expect(refHopsAround.refs.hopRef).toEqual(secondDiv);
254
- expect(refHopsAround.refs.divThreeRef).toEqual(thirdDiv);
289
+ expect(refHopsAround.divOneRef.current).toEqual(firstDiv);
290
+ expect(refHopsAround.hopRef.current).toEqual(secondDiv);
291
+ expect(refHopsAround.divThreeRef.current).toEqual(thirdDiv);
292
293
refHopsAround.moveRef();
257
- expect(refHopsAround.refs.divOneRef).toEqual(firstDiv);
258
- expect(refHopsAround.refs.divTwoRef).toEqual(secondDiv);
259
- expect(refHopsAround.refs.hopRef).toEqual(thirdDiv);
294
+ expect(refHopsAround.divOneRef.current).toEqual(firstDiv);
295
+ expect(refHopsAround.divTwoRef.current).toEqual(secondDiv);
296
+ expect(refHopsAround.hopRef.current).toEqual(thirdDiv);
297
298
/**
299
* Make sure that after the third, we're back to where we started and the
300
* refs are completely restored.
301
*/
302
refHopsAround.moveRef();
266
- expect(refHopsAround.refs.hopRef).toEqual(firstDiv);
267
- expect(refHopsAround.refs.divTwoRef).toEqual(secondDiv);
268
- expect(refHopsAround.refs.divThreeRef).toEqual(thirdDiv);
303
+ expect(refHopsAround.hopRef.current).toEqual(firstDiv);
304
+ expect(refHopsAround.divTwoRef.current).toEqual(secondDiv);
305
+ expect(refHopsAround.divThreeRef.current).toEqual(thirdDiv);
306
});
307
308
it('always has a value for this.refs', () => {
@@ -309,7 +346,20 @@ describe('ref swapping', () => {
346
return <div ref={1} />;
347
}
348
}
312
- const a = ReactTestUtils.renderIntoDocument(<A />);
349
+ let a;
350
+ expect(() => {
351
+ a = ReactTestUtils.renderIntoDocument(<A />);
352
+ }).toErrorDev(
353
+ ReactFeatureFlags.warnAboutStringRefs
354
+ ? [
355
+ 'Warning: Component "A" contains the string ref "1". ' +
356
+ 'Support for string refs will be removed in a future major release. ' +
357
+ 'We recommend using useRef() or createRef() instead. ' +
358
+ 'Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref\n' +
359
+ ' in A (at **)',
360
+ ]
361
+ : [],
362
+ );
363
expect(a.refs[1].nodeName).toBe('DIV');
364
});
365
@@ -464,7 +514,7 @@ describe('root level refs', () => {
514
});
515
});
516
467
-describe('creating element with ref in constructor', () => {
517
+describe('creating element with string ref in constructor', () => {
518
class RefTest extends React.Component {
519
constructor(props) {
520
super(props);
@@ -521,13 +571,41 @@ describe('strings refs across renderers', () => {
571
572
const div1 = document.createElement('div');
573
const div2 = document.createElement('div');
524
- const inst = ReactDOM.render(<Parent />, div1);
574
+
575
+ let inst;
576
+ expect(() => {
577
+ inst = ReactDOM.render(<Parent />, div1);
578
+ }).toErrorDev(
579
+ ReactFeatureFlags.warnAboutStringRefs
580
+ ? [
581
+ 'Warning: Component "Indirection" contains the string ref "child1". ' +
582
+ 'Support for string refs will be removed in a future major release. ' +
583
+ 'We recommend using useRef() or createRef() instead. ' +
584
+ 'Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref\n' +
585
+ ' in Indirection (at **)\n' +
586
+ ' in Parent (at **)',
587
+ ]
588
+ : [],
589
+ );
590
+
591
// Only the first ref has rendered yet.
592
expect(inst.refs.child1.tagName).toBe('DIV');
593
expect(inst.refs.child1).toBe(div1.firstChild);
594
529
- // Now both refs should be rendered.
530
- ReactDOM.render(<Parent />, div1);
595
+ expect(() => {
596
+ // Now both refs should be rendered.
597
+ ReactDOM.render(<Parent />, div1);
598
+ }).toErrorDev(
599
+ ReactFeatureFlags.warnAboutStringRefs
600
+ ? [
601
+ 'Warning: Component "Root" contains the string ref "child2". ' +
602
+ 'Support for string refs will be removed in a future major release. ' +
603
+ 'We recommend using useRef() or createRef() instead. ' +
604
+ 'Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref',
605
+ ]
606
+ : [],
607
+ {withoutStack: true},
608
+ );
609
expect(inst.refs.child1.tagName).toBe('DIV');
610
expect(inst.refs.child1).toBe(div1.firstChild);
611
expect(inst.refs.child2.tagName).toBe('DIV');
packages/react-native-renderer/src/__tests__/ResponderEventPlugin-test.internal.js
+42
-27
@@ -1385,25 +1385,36 @@ describe('ResponderEventPlugin', () => {
1385
const ReactDOMComponentTree = require('react-dom-bindings/src/client/ReactDOMComponentTree');
1386
1387
class ChildComponent extends React.Component {
1388
+ divRef = React.createRef();
1389
+ div1Ref = React.createRef();
1390
+ div2Ref = React.createRef();
1391
+
1392
render() {
1393
return (
1390
- <div ref="DIV" id={this.props.id + '__DIV'}>
1391
- <div ref="DIV_1" id={this.props.id + '__DIV_1'} />
1392
- <div ref="DIV_2" id={this.props.id + '__DIV_2'} />
1394
+ <div ref={this.divRef} id={this.props.id + '__DIV'}>
1395
+ <div ref={this.div1Ref} id={this.props.id + '__DIV_1'} />
1396
+ <div ref={this.div2Ref} id={this.props.id + '__DIV_2'} />
1397
</div>
1398
);
1399
}
1400
}
1401
1402
class ParentComponent extends React.Component {
1403
+ pRef = React.createRef();
1404
+ p_P1Ref = React.createRef();
1405
+ p_P1Ref = React.createRef();
1406
+ p_P1_C1Ref = React.createRef();
1407
+ p_P1_C2Ref = React.createRef();
1408
+ p_OneOffRef = React.createRef();
1409
+
1410
render() {
1411
return (
1401
- <div ref="P" id="P">
1402
- <div ref="P_P1" id="P_P1">
1403
- <ChildComponent ref="P_P1_C1" id="P_P1_C1" />
1404
- <ChildComponent ref="P_P1_C2" id="P_P1_C2" />
1412
+ <div ref={this.pRef} id="P">
1413
+ <div ref={this.p_P1Ref} id="P_P1">
1414
+ <ChildComponent ref={this.p_P1_C1Ref} id="P_P1_C1" />
1415
+ <ChildComponent ref={this.p_P1_C2Ref} id="P_P1_C2" />
1416
</div>
1406
- <div ref="P_OneOff" id="P_OneOff" />
1417
+ <div ref={this.p_OneOffRef} id="P_OneOff" />
1418
</div>
1419
);
1420
}
@@ -1414,41 +1425,45 @@ describe('ResponderEventPlugin', () => {
1425
const ancestors = [
1426
// Common ancestor with self is self.
1427
{
1417
- one: parent.refs.P_P1_C1.refs.DIV_1,
1418
- two: parent.refs.P_P1_C1.refs.DIV_1,
1419
- com: parent.refs.P_P1_C1.refs.DIV_1,
1428
+ one: parent.p_P1_C1Ref.current.div1Ref.current,
1429
+ two: parent.p_P1_C1Ref.current.div1Ref.current,
1430
+ com: parent.p_P1_C1Ref.current.div1Ref.current,
1431
},
1432
// Common ancestor with self is self - even if topmost DOM.
1422
- {one: parent.refs.P, two: parent.refs.P, com: parent.refs.P},
1433
+ {
1434
+ one: parent.pRef.current,
1435
+ two: parent.pRef.current,
1436
+ com: parent.pRef.current,
1437
+ },
1438
// Siblings
1439
{
1425
- one: parent.refs.P_P1_C1.refs.DIV_1,
1426
- two: parent.refs.P_P1_C1.refs.DIV_2,
1427
- com: parent.refs.P_P1_C1.refs.DIV,
1440
+ one: parent.p_P1_C1Ref.current.div1Ref.current,
1441
+ two: parent.p_P1_C1Ref.current.div2Ref.current,
1442
+ com: parent.p_P1_C1Ref.current.divRef.current,
1443
},
1444
// Common ancestor with parent is the parent.
1445
{
1431
- one: parent.refs.P_P1_C1.refs.DIV_1,
1432
- two: parent.refs.P_P1_C1.refs.DIV,
1433
- com: parent.refs.P_P1_C1.refs.DIV,
1446
+ one: parent.p_P1_C1Ref.current.div1Ref.current,
1447
+ two: parent.p_P1_C1Ref.current.divRef.current,
1448
+ com: parent.p_P1_C1Ref.current.divRef.current,
1449
},
1450
// Common ancestor with grandparent is the grandparent.
1451
{
1437
- one: parent.refs.P_P1_C1.refs.DIV_1,
1438
- two: parent.refs.P_P1,
1439
- com: parent.refs.P_P1,
1452
+ one: parent.p_P1_C1Ref.current.div1Ref.current,
1453
+ two: parent.p_P1Ref.current,
1454
+ com: parent.p_P1Ref.current,
1455
},
1456
// Grandparent across subcomponent boundaries.
1457
{
1443
- one: parent.refs.P_P1_C1.refs.DIV_1,
1444
- two: parent.refs.P_P1_C2.refs.DIV_1,
1445
- com: parent.refs.P_P1,
1458
+ one: parent.p_P1_C1Ref.current.div1Ref.current,
1459
+ two: parent.p_P1_C2Ref.current.div1Ref.current,
1460
+ com: parent.p_P1Ref.current,
1461
},
1462
// Something deep with something one-off.
1463
{
1449
- one: parent.refs.P_P1_C1.refs.DIV_1,
1450
- two: parent.refs.P_OneOff,
1451
- com: parent.refs.P,
1464
+ one: parent.p_P1_C1Ref.current.div1Ref.current,
1465
+ two: parent.p_OneOffRef.current,
1466
+ com: parent.pRef.current,
1467
},
1468
];
1469
let i;
packages/react-reconciler/src/ReactChildFiber.new.js
+14
-1
@@ -97,6 +97,10 @@ if (__DEV__) {
97
};
98
}
99
100
+function isReactClass(type) {
101
+ return type.prototype && type.prototype.isReactComponent;
102
+}
103
+
104
function coerceRef(
105
returnFiber: Fiber,
106
current: Fiber | null,
@@ -120,7 +124,16 @@ function coerceRef(
124
element._owner &&
125
element._self &&
126
element._owner.stateNode !== element._self
123
- )
127
+ ) &&
128
+ // Will already throw with "Function components cannot have string refs"
129
+ !(
130
+ element._owner &&
131
+ ((element._owner: any): Fiber).tag !== ClassComponent
132
+ ) &&
133
+ // Will already warn with "Function components cannot be given refs"
134
+ !(typeof element.type === 'function' && !isReactClass(element.type)) &&
135
+ // Will already throw with "Element ref was specified as a string (someStringRef) but no owner was set"
136
+ element._owner
137
) {
138
const componentName =
139
getComponentNameFromFiber(returnFiber) || 'Component';
packages/react-reconciler/src/ReactChildFiber.old.js
+14
-1
@@ -97,6 +97,10 @@ if (__DEV__) {
97
};
98
}
99
100
+function isReactClass(type) {
101
+ return type.prototype && type.prototype.isReactComponent;
102
+}
103
+
104
function coerceRef(
105
returnFiber: Fiber,
106
current: Fiber | null,
@@ -120,7 +124,16 @@ function coerceRef(
124
element._owner &&
125
element._self &&
126
element._owner.stateNode !== element._self
123
- )
127
+ ) &&
128
+ // Will already throw with "Function components cannot have string refs"
129
+ !(
130
+ element._owner &&
131
+ ((element._owner: any): Fiber).tag !== ClassComponent
132
+ ) &&
133
+ // Will already warn with "Function components cannot be given refs"
134
+ !(typeof element.type === 'function' && !isReactClass(element.type)) &&
135
+ // Will already throw with "Element ref was specified as a string (someStringRef) but no owner was set"
136
+ element._owner
137
) {
138
const componentName =
139
getComponentNameFromFiber(returnFiber) || 'Component';
packages/react-reconciler/src/__tests__/ReactIncrementalSideEffects-test.js
+15
-2
@@ -11,6 +11,7 @@
11
'use strict';
12
13
let React;
14
+let ReactFeatureFlags;
15
let ReactNoop;
16
let Scheduler;
17
@@ -19,6 +20,7 @@ describe('ReactIncrementalSideEffects', () => {
20
jest.resetModules();
21
22
React = require('react');
23
+ ReactFeatureFlags = require('shared/ReactFeatureFlags');
24
ReactNoop = require('react-noop-renderer');
25
Scheduler = require('scheduler');
26
});
@@ -1306,8 +1308,19 @@ describe('ReactIncrementalSideEffects', () => {
1308
}
1309
1310
ReactNoop.render(<Foo />);
1309
- expect(Scheduler).toFlushWithoutYielding();
1310
-
1311
+ expect(() => {
1312
+ expect(Scheduler).toFlushWithoutYielding();
1313
+ }).toErrorDev(
1314
+ ReactFeatureFlags.warnAboutStringRefs
1315
+ ? [
1316
+ 'Warning: Component "Foo" contains the string ref "bar". ' +
1317
+ 'Support for string refs will be removed in a future major release. ' +
1318
+ 'We recommend using useRef() or createRef() instead. ' +
1319
+ 'Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref\n' +
1320
+ ' in Foo (at **)',
1321
+ ]
1322
+ : [],
1323
+ );
1324
expect(fooInstance.refs.bar.test).toEqual('test');
1325
});
1326
});
packages/react-test-renderer/src/__tests__/ReactTestRenderer-test.internal.js
+13
-6
@@ -271,13 +271,15 @@ describe('ReactTestRenderer', () => {
271
return <div>Hello, world</div>;
272
}
273
class Foo extends React.Component {
274
+ fooRef = React.createRef();
275
render() {
275
- return <Bar ref="foo" />;
276
+ return <Bar ref={this.fooRef} />;
277
}
278
}
279
class Baz extends React.Component {
280
+ bazRef = React.createRef();
281
render() {
280
- return <div ref="baz" />;
282
+ return <div ref={this.bazRef} />;
283
}
284
}
285
ReactTestRenderer.create(<Baz />);
@@ -298,11 +300,12 @@ describe('ReactTestRenderer', () => {
300
const mockAnchorInstance = {hover: () => {}};
301
const log = [];
302
class Foo extends React.Component {
303
+ barRef = React.createRef();
304
componentDidMount() {
302
- log.push(this.refs.bar);
305
+ log.push(this.barRef.current);
306
}
307
render() {
305
- return <a ref="bar">Hello, world</a>;
308
+ return <a ref={this.barRef}>Hello, world</a>;
309
}
310
}
311
function createNodeMock(element) {
@@ -355,7 +358,7 @@ describe('ReactTestRenderer', () => {
358
it('supports unmounting when using refs', () => {
359
class Foo extends React.Component {
360
render() {
358
- return <div ref="foo" />;
361
+ return <div ref={React.createRef()} />;
362
}
363
}
364
const inst = ReactTestRenderer.create(<Foo />, {
@@ -394,7 +397,11 @@ describe('ReactTestRenderer', () => {
397
};
398
class Foo extends React.Component {
399
render() {
397
- return this.props.useDiv ? <div ref="foo" /> : <span ref="foo" />;
400
+ return this.props.useDiv ? (
401
+ <div ref={React.createRef()} />
402
+ ) : (
403
+ <span ref={React.createRef()} />
404
+ );
405
}
406
}
407
const inst = ReactTestRenderer.create(<Foo useDiv={true} />, {
packages/react/src/__tests__/ReactCoffeeScriptClass-test.coffee
+16
-2
@@ -9,6 +9,7 @@ PropTypes = null
9
React = null
10
ReactDOM = null
11
ReactDOMClient = null
12
+ReactFeatureFlags = null
13
act = null
14
15
describe 'ReactCoffeeScriptClass', ->
@@ -22,6 +23,7 @@ describe 'ReactCoffeeScriptClass', ->
23
React = require 'react'
24
ReactDOM = require 'react-dom'
25
ReactDOMClient = require 'react-dom/client'
26
+ ReactFeatureFlags = require 'shared/ReactFeatureFlags'
27
act = require('jest-react').act
28
PropTypes = require 'prop-types'
29
container = document.createElement 'div'
@@ -528,7 +530,7 @@ describe 'ReactCoffeeScriptClass', ->
530
531
test React.createElement(Foo), 'DIV', 'bar-through-context'
532
531
- it 'supports classic refs', ->
533
+ it 'supports string refs', ->
534
class Foo extends React.Component
535
render: ->
536
React.createElement(InnerComponent,
@@ -537,7 +539,19 @@ describe 'ReactCoffeeScriptClass', ->
539
)
540
541
ref = React.createRef()
540
- test(React.createElement(Foo, ref: ref), 'DIV', 'foo')
542
+ expect(->
543
+ test(React.createElement(Foo, ref: ref), 'DIV', 'foo')
544
+ ).toErrorDev(
545
+ if ReactFeatureFlags.warnAboutStringRefs
546
+ then [
547
+ 'Warning: Component "Foo" contains the string ref "inner". ' +
548
+ 'Support for string refs will be removed in a future major release. ' +
549
+ 'We recommend using useRef() or createRef() instead. ' +
550
+ 'Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref\n' +
551
+ ' in Foo (at **)'
552
+ ]
553
+ else []
554
+ );
555
expect(ref.current.refs.inner.getName()).toBe 'foo'
556
557
it 'supports drilling through to the DOM using findDOMNode', ->
packages/react/src/__tests__/ReactContextValidator-test.js
+4
-2
@@ -46,6 +46,8 @@ describe('ReactContextValidator', () => {
46
};
47
48
class ComponentInFooBarContext extends React.Component {
49
+ childRef = React.createRef();
50
+
51
getChildContext() {
52
return {
53
foo: 'abc',
@@ -54,7 +56,7 @@ describe('ReactContextValidator', () => {
56
}
57
58
render() {
57
- return <Component ref="child" />;
59
+ return <Component ref={this.childRef} />;
60
}
61
}
62
ComponentInFooBarContext.childContextTypes = {
@@ -65,7 +67,7 @@ describe('ReactContextValidator', () => {
67
const instance = ReactTestUtils.renderIntoDocument(
68
<ComponentInFooBarContext />,
69
);
68
- expect(instance.refs.child.context).toEqual({foo: 'abc'});
70
+ expect(instance.childRef.current.context).toEqual({foo: 'abc'});
71
});
72
73
it('should pass next context to lifecycles', () => {
packages/react/src/__tests__/ReactES6Class-test.js
+16
-2
@@ -13,6 +13,7 @@ let PropTypes;
13
let React;
14
let ReactDOM;
15
let ReactDOMClient;
16
+let ReactFeatureFlags;
17
let act;
18
19
describe('ReactES6Class', () => {
@@ -31,6 +32,7 @@ describe('ReactES6Class', () => {
32
React = require('react');
33
ReactDOM = require('react-dom');
34
ReactDOMClient = require('react-dom/client');
35
+ ReactFeatureFlags = require('shared/ReactFeatureFlags');
36
act = require('jest-react').act;
37
container = document.createElement('div');
38
root = ReactDOMClient.createRoot(container);
@@ -568,14 +570,26 @@ describe('ReactES6Class', () => {
570
test(<Foo />, 'DIV', 'bar-through-context');
571
});
572
571
- it('supports classic refs', () => {
573
+ it('supports string refs', () => {
574
class Foo extends React.Component {
575
render() {
576
return <Inner name="foo" ref="inner" />;
577
}
578
}
579
const ref = React.createRef();
578
- test(<Foo ref={ref} />, 'DIV', 'foo');
580
+ expect(() => {
581
+ test(<Foo ref={ref} />, 'DIV', 'foo');
582
+ }).toErrorDev(
583
+ ReactFeatureFlags.warnAboutStringRefs
584
+ ? [
585
+ 'Warning: Component "Foo" contains the string ref "inner". ' +
586
+ 'Support for string refs will be removed in a future major release. ' +
587
+ 'We recommend using useRef() or createRef() instead. ' +
588
+ 'Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref\n' +
589
+ ' in Foo (at **)',
590
+ ]
591
+ : [],
592
+ );
593
expect(ref.current.refs.inner.getName()).toBe('foo');
594
});
595
packages/react/src/__tests__/ReactElement-test.js
+1
-1
@@ -93,7 +93,7 @@ describe('ReactElement', () => {
93
render() {
94
return (
95
<div>
96
- <Child ref="childElement" />
96
+ <Child ref={React.createRef()} />
97
</div>
98
);
99
}
packages/react/src/__tests__/ReactElementClone-test.js
+24
-11
@@ -82,8 +82,10 @@ describe('ReactElementClone', () => {
82
83
it('should keep the original ref if it is not overridden', () => {
84
class Grandparent extends React.Component {
85
+ yoloRef = React.createRef();
86
+
87
render() {
86
- return <Parent child={<div ref="yolo" />} />;
88
+ return <Parent child={<div ref={this.yoloRef} />} />;
89
}
90
}
91
@@ -96,7 +98,7 @@ describe('ReactElementClone', () => {
98
}
99
100
const component = ReactTestUtils.renderIntoDocument(<Grandparent />);
99
- expect(component.refs.yolo.tagName).toBe('DIV');
101
+ expect(component.yoloRef.current.tagName).toBe('DIV');
102
});
103
104
it('should transfer the key property', () => {
@@ -174,21 +176,25 @@ describe('ReactElementClone', () => {
176
177
it('should support keys and refs', () => {
178
class Parent extends React.Component {
179
+ xyzRef = React.createRef();
180
+
181
render() {
182
const clone = React.cloneElement(this.props.children, {
183
key: 'xyz',
180
- ref: 'xyz',
184
+ ref: this.xyzRef,
185
});
186
expect(clone.key).toBe('xyz');
183
- expect(clone.ref).toBe('xyz');
187
+ expect(clone.ref).toBe(this.xyzRef);
188
return <div>{clone}</div>;
189
}
190
}
191
192
class Grandparent extends React.Component {
193
+ parentRef = React.createRef();
194
+
195
render() {
196
return (
191
- <Parent ref="parent">
197
+ <Parent ref={this.parentRef}>
198
<span key="abc" />
199
</Parent>
200
);
@@ -196,30 +202,37 @@ describe('ReactElementClone', () => {
202
}
203
204
const component = ReactTestUtils.renderIntoDocument(<Grandparent />);
199
- expect(component.refs.parent.refs.xyz.tagName).toBe('SPAN');
205
+ expect(component.parentRef.current.xyzRef.current.tagName).toBe('SPAN');
206
});
207
208
it('should steal the ref if a new ref is specified', () => {
209
class Parent extends React.Component {
210
+ xyzRef = React.createRef();
211
+
212
render() {
205
- const clone = React.cloneElement(this.props.children, {ref: 'xyz'});
213
+ const clone = React.cloneElement(this.props.children, {
214
+ ref: this.xyzRef,
215
+ });
216
return <div>{clone}</div>;
217
}
218
}
219
220
class Grandparent extends React.Component {
221
+ parentRef = React.createRef();
222
+ childRef = React.createRef();
223
+
224
render() {
225
return (
213
- <Parent ref="parent">
214
- <span ref="child" />
226
+ <Parent ref={this.parentRef}>
227
+ <span ref={this.childRef} />
228
</Parent>
229
);
230
}
231
}
232
233
const component = ReactTestUtils.renderIntoDocument(<Grandparent />);
221
- expect(component.refs.child).toBeUndefined();
222
- expect(component.refs.parent.refs.xyz.tagName).toBe('SPAN');
234
+ expect(component.childRef).toEqual({current: null});
235
+ expect(component.parentRef.current.xyzRef.current.tagName).toBe('SPAN');
236
});
237
238
it('should overwrite props', () => {
packages/react/src/__tests__/ReactElementJSX-test.js
+1
-1
@@ -221,7 +221,7 @@ describe('ReactElement.jsx', () => {
221
class Parent extends React.Component {
222
render() {
223
return JSXRuntime.jsx('div', {
224
- children: JSXRuntime.jsx(Child, {ref: 'childElement'}),
224
+ children: JSXRuntime.jsx(Child, {ref: React.createRef()}),
225
});
226
}
227
}
packages/react/src/__tests__/ReactJSXElement-test.js
+3
-2
@@ -78,10 +78,11 @@ describe('ReactJSXElement', () => {
78
});
79
80
it('extracts key and ref from the rest of the props', () => {
81
- const element = <Component key="12" ref="34" foo="56" />;
81
+ const ref = React.createRef();
82
+ const element = <Component key="12" ref={ref} foo="56" />;
83
expect(element.type).toBe(Component);
84
expect(element.key).toBe('12');
84
- expect(element.ref).toBe('34');
85
+ expect(element.ref).toBe(ref);
86
const expectation = {foo: '56'};
87
Object.freeze(expectation);
88
expect(element.props).toEqual(expectation);
packages/react/src/__tests__/ReactStrictMode-test.js
+26
-13
@@ -926,12 +926,18 @@ describe('string refs', () => {
926
expect(() => {
927
ReactDOM.render(<OuterComponent />, container);
928
}).toErrorDev(
929
- 'Warning: A string ref, "somestring", has been found within a strict mode tree. ' +
930
- 'String refs are a source of potential bugs and should be avoided. ' +
931
- 'We recommend using useRef() or createRef() instead. ' +
932
- 'Learn more about using refs safely here: ' +
933
- 'https://reactjs.org/link/strict-mode-string-ref\n' +
934
- ' in OuterComponent (at **)',
929
+ ReactFeatureFlags.warnAboutStringRefs
930
+ ? 'Warning: Component "StrictMode" contains the string ref "somestring". ' +
931
+ 'Support for string refs will be removed in a future major release. ' +
932
+ 'We recommend using useRef() or createRef() instead. ' +
933
+ 'Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref\n' +
934
+ ' in OuterComponent (at **)'
935
+ : 'Warning: A string ref, "somestring", has been found within a strict mode tree. ' +
936
+ 'String refs are a source of potential bugs and should be avoided. ' +
937
+ 'We recommend using useRef() or createRef() instead. ' +
938
+ 'Learn more about using refs safely here: ' +
939
+ 'https://reactjs.org/link/strict-mode-string-ref\n' +
940
+ ' in OuterComponent (at **)',
941
);
942
943
// Dedup
@@ -967,13 +973,20 @@ describe('string refs', () => {
973
expect(() => {
974
ReactDOM.render(<OuterComponent />, container);
975
}).toErrorDev(
970
- 'Warning: A string ref, "somestring", has been found within a strict mode tree. ' +
971
- 'String refs are a source of potential bugs and should be avoided. ' +
972
- 'We recommend using useRef() or createRef() instead. ' +
973
- 'Learn more about using refs safely here: ' +
974
- 'https://reactjs.org/link/strict-mode-string-ref\n' +
975
- ' in InnerComponent (at **)\n' +
976
- ' in OuterComponent (at **)',
976
+ ReactFeatureFlags.warnAboutStringRefs
977
+ ? 'Warning: Component "InnerComponent" contains the string ref "somestring". ' +
978
+ 'Support for string refs will be removed in a future major release. ' +
979
+ 'We recommend using useRef() or createRef() instead. ' +
980
+ 'Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref\n' +
981
+ ' in InnerComponent (at **)\n' +
982
+ ' in OuterComponent (at **)'
983
+ : 'Warning: A string ref, "somestring", has been found within a strict mode tree. ' +
984
+ 'String refs are a source of potential bugs and should be avoided. ' +
985
+ 'We recommend using useRef() or createRef() instead. ' +
986
+ 'Learn more about using refs safely here: ' +
987
+ 'https://reactjs.org/link/strict-mode-string-ref\n' +
988
+ ' in InnerComponent (at **)\n' +
989
+ ' in OuterComponent (at **)',
990
);
991
992
// Dedup
packages/react/src/__tests__/ReactTypeScriptClass-test.ts
+15
-2
@@ -17,6 +17,7 @@ import ReactDOMClient = require('react-dom/client');
17
import ReactDOMTestUtils = require('react-dom/test-utils');
18
import PropTypes = require('prop-types');
19
import internalAct = require('jest-react');
20
+import ReactFeatureFlags = require('shared/ReactFeatureFlags')
21
22
// Before Each
23
@@ -686,9 +687,21 @@ describe('ReactTypeScriptClass', function() {
687
test(React.createElement(ProvideContext), 'DIV', 'bar-through-context');
688
});
689
689
- it('supports classic refs', function() {
690
+ it('supports string refs', function() {
691
const ref = React.createRef();
691
- test(React.createElement(ClassicRefs, {ref: ref}), 'DIV', 'foo');
692
+ expect(() => {
693
+ test(React.createElement(ClassicRefs, {ref: ref}), 'DIV', 'foo');
694
+ }).toErrorDev(
695
+ ReactFeatureFlags.warnAboutStringRefs
696
+ ? [
697
+ 'Warning: Component "ClassicRefs" contains the string ref "inner". ' +
698
+ 'Support for string refs will be removed in a future major release. ' +
699
+ 'We recommend using useRef() or createRef() instead. ' +
700
+ 'Learn more about using refs safely here: https://reactjs.org/link/strict-mode-string-ref\n' +
701
+ ' in ClassicRefs (at **)',
702
+ ]
703
+ : [],
704
+ );
705
expect(ref.current.refs.inner.getName()).toBe('foo');
706
});
707
packages/shared/ReactFeatureFlags.js
+1
-1
@@ -219,7 +219,7 @@ export const warnAboutDefaultPropsOnFunctionComponents = false; // deprecate lat
219
// a deprecated pattern we want to get rid of in the future
220
export const warnAboutSpreadingKeyToJSX = true;
221
222
-export const warnAboutStringRefs = false;
222
+export const warnAboutStringRefs = true;
223
224
// -----------------------------------------------------------------------------
225
// Debugging and DevTools
packages/shared/forks/ReactFeatureFlags.native-fb.js
+1
-1
@@ -42,7 +42,7 @@ export const enableScopeAPI = false;
42
export const enableCreateEventHandleAPI = false;
43
export const enableSuspenseCallback = false;
44
export const warnAboutDefaultPropsOnFunctionComponents = false;
45
-export const warnAboutStringRefs = false;
45
+export const warnAboutStringRefs = true;
46
export const disableLegacyContext = false;
47
export const disableSchedulerTimeoutBasedOnReactExpirationTime = false;
48
export const enableTrustedTypesIntegration = false;
packages/shared/forks/ReactFeatureFlags.native-oss.js
+1
-1
@@ -32,7 +32,7 @@ export const enableScopeAPI = false;
32
export const enableCreateEventHandleAPI = false;
33
export const enableSuspenseCallback = false;
34
export const warnAboutDefaultPropsOnFunctionComponents = false;
35
-export const warnAboutStringRefs = false;
35
+export const warnAboutStringRefs = true;
36
export const disableLegacyContext = false;
37
export const disableSchedulerTimeoutBasedOnReactExpirationTime = false;
38
export const enableTrustedTypesIntegration = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.js
+1
-1
@@ -32,7 +32,7 @@ export const enableScopeAPI = false;
32
export const enableCreateEventHandleAPI = false;
33
export const enableSuspenseCallback = false;
34
export const warnAboutDefaultPropsOnFunctionComponents = false;
35
-export const warnAboutStringRefs = false;
35
+export const warnAboutStringRefs = true;
36
export const disableLegacyContext = false;
37
export const disableSchedulerTimeoutBasedOnReactExpirationTime = false;
38
export const enableTrustedTypesIntegration = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.native.js
+1
-1
@@ -32,7 +32,7 @@ export const enableScopeAPI = false;
32
export const enableCreateEventHandleAPI = false;
33
export const enableSuspenseCallback = false;
34
export const warnAboutDefaultPropsOnFunctionComponents = false;
35
-export const warnAboutStringRefs = false;
35
+export const warnAboutStringRefs = true;
36
export const disableLegacyContext = false;
37
export const disableSchedulerTimeoutBasedOnReactExpirationTime = false;
38
export const enableTrustedTypesIntegration = false;
packages/shared/forks/ReactFeatureFlags.test-renderer.www.js
+1
-1
@@ -32,7 +32,7 @@ export const enableScopeAPI = true;
32
export const enableCreateEventHandleAPI = false;
33
export const enableSuspenseCallback = true;
34
export const warnAboutDefaultPropsOnFunctionComponents = false;
35
-export const warnAboutStringRefs = false;
35
+export const warnAboutStringRefs = true;
36
export const disableLegacyContext = false;
37
export const disableSchedulerTimeoutBasedOnReactExpirationTime = false;
38
export const enableTrustedTypesIntegration = false;
packages/shared/forks/ReactFeatureFlags.testing.js
+1
-1
@@ -32,7 +32,7 @@ export const enableScopeAPI = false;
32
export const enableCreateEventHandleAPI = false;
33
export const enableSuspenseCallback = false;
34
export const warnAboutDefaultPropsOnFunctionComponents = false;
35
-export const warnAboutStringRefs = false;
35
+export const warnAboutStringRefs = true;
36
export const disableLegacyContext = false;
37
export const disableSchedulerTimeoutBasedOnReactExpirationTime = false;
38
export const enableTrustedTypesIntegration = false;
packages/shared/forks/ReactFeatureFlags.testing.www.js
+1
-1
@@ -32,7 +32,7 @@ export const enableScopeAPI = true;
32
export const enableCreateEventHandleAPI = true;
33
export const enableSuspenseCallback = true;
34
export const warnAboutDefaultPropsOnFunctionComponents = false;
35
-export const warnAboutStringRefs = false;
35
+export const warnAboutStringRefs = true;
36
export const disableLegacyContext = __EXPERIMENTAL__;
37
export const disableSchedulerTimeoutBasedOnReactExpirationTime = false;
38
export const enableTrustedTypesIntegration = false;
packages/shared/forks/ReactFeatureFlags.www.js
+1
-1
@@ -66,7 +66,7 @@ export const enableSchedulingProfiler: boolean =
66
export const enableSchedulerDebugging = true;
67
export const warnAboutDeprecatedLifecycles = true;
68
export const disableLegacyContext = __EXPERIMENTAL__;
69
-export const warnAboutStringRefs = false;
69
+export const warnAboutStringRefs = true;
70
export const warnAboutDefaultPropsOnFunctionComponents = false;
71
export const enableGetInspectorDataForInstanceInProduction = false;
72