Skip to content

Commit 5c1f10e

Browse files
committed
Remove enableRefAsProp feature flag
**NOTE:** To be merged after React 19 is released. The flag is fully rolled out.
1 parent fee423e commit 5c1f10e

29 files changed

+109
-757
lines changed

packages/jest-react/src/JestReact.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
*/
77

88
import {REACT_ELEMENT_TYPE, REACT_FRAGMENT_TYPE} from 'shared/ReactSymbols';
9-
import {disableStringRefs, enableRefAsProp} from 'shared/ReactFeatureFlags';
9+
import {disableStringRefs} from 'shared/ReactFeatureFlags';
1010
const {assertConsoleLogsCleared} = require('internal-test-utils/consoleMock');
1111

1212
import isArray from 'shared/isArray';
@@ -42,7 +42,7 @@ function assertYieldsWereCleared(root) {
4242
}
4343

4444
function createJSXElementForTestComparison(type, props) {
45-
if (__DEV__ && enableRefAsProp) {
45+
if (__DEV__) {
4646
const element = {
4747
$$typeof: REACT_ELEMENT_TYPE,
4848
type: type,

packages/react-client/src/ReactFlightClient.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ import {
4141
disableStringRefs,
4242
enableBinaryFlight,
4343
enablePostpone,
44-
enableRefAsProp,
4544
enableFlightReadableStream,
4645
enableOwnerStacks,
4746
} from 'shared/ReactFeatureFlags';
@@ -630,7 +629,7 @@ function createElement(
630629
| React$Element<any>
631630
| LazyComponent<React$Element<any>, SomeChunk<React$Element<any>>> {
632631
let element: any;
633-
if (__DEV__ && enableRefAsProp) {
632+
if (__DEV__) {
634633
// `ref` is non-enumerable in dev
635634
element = ({
636635
$$typeof: REACT_ELEMENT_TYPE,

packages/react-devtools-shared/src/__tests__/legacy/storeLegacy-v15-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -873,7 +873,7 @@ describe('Store (legacy)', () => {
873873
// is not compatible with older versions of React. Need to configure the
874874
// the test environment in such a way that certain test modules like this
875875
// one can use an older transform.
876-
if (!require('shared/ReactFeatureFlags').enableRefAsProp) {
876+
if (false) {
877877
it('should support expanding deep parts of the tree', () => {
878878
const Wrapper = ({forwardedRef}) =>
879879
React.createElement(Nested, {

packages/react-dom/src/__tests__/ReactFunctionComponent-test.js

Lines changed: 0 additions & 217 deletions
Original file line numberDiff line numberDiff line change
@@ -197,223 +197,6 @@ describe('ReactFunctionComponent', () => {
197197
.rejects.toThrowError();
198198
});
199199

200-
// @gate !enableRefAsProp || !__DEV__
201-
it('should warn when given a string ref', async () => {
202-
function Indirection(props) {
203-
return <div>{props.children}</div>;
204-
}
205-
206-
class ParentUsingStringRef extends React.Component {
207-
render() {
208-
return (
209-
<Indirection>
210-
<FunctionComponent name="A" ref="stateless" />
211-
</Indirection>
212-
);
213-
}
214-
}
215-
216-
await expect(async () => {
217-
const container = document.createElement('div');
218-
const root = ReactDOMClient.createRoot(container);
219-
await act(() => {
220-
root.render(<ParentUsingStringRef />);
221-
});
222-
}).toErrorDev(
223-
'Function components cannot be given refs. ' +
224-
'Attempts to access this ref will fail. ' +
225-
'Did you mean to use React.forwardRef()?\n\n' +
226-
'Check the render method ' +
227-
'of `ParentUsingStringRef`.\n' +
228-
' in FunctionComponent (at **)\n' +
229-
' in div (at **)\n' +
230-
' in Indirection (at **)\n' +
231-
' in ParentUsingStringRef (at **)',
232-
);
233-
234-
// No additional warnings should be logged
235-
const container = document.createElement('div');
236-
const root = ReactDOMClient.createRoot(container);
237-
await act(() => {
238-
root.render(<ParentUsingStringRef />);
239-
});
240-
});
241-
242-
// @gate !enableRefAsProp || !__DEV__
243-
it('should warn when given a function ref', async () => {
244-
function Indirection(props) {
245-
return <div>{props.children}</div>;
246-
}
247-
248-
const ref = jest.fn();
249-
class ParentUsingFunctionRef extends React.Component {
250-
render() {
251-
return (
252-
<Indirection>
253-
<FunctionComponent name="A" ref={ref} />
254-
</Indirection>
255-
);
256-
}
257-
}
258-
259-
await expect(async () => {
260-
const container = document.createElement('div');
261-
const root = ReactDOMClient.createRoot(container);
262-
await act(() => {
263-
root.render(<ParentUsingFunctionRef />);
264-
});
265-
}).toErrorDev(
266-
'Function components cannot be given refs. ' +
267-
'Attempts to access this ref will fail. ' +
268-
'Did you mean to use React.forwardRef()?\n\n' +
269-
'Check the render method ' +
270-
'of `ParentUsingFunctionRef`.\n' +
271-
' in FunctionComponent (at **)\n' +
272-
' in div (at **)\n' +
273-
' in Indirection (at **)\n' +
274-
' in ParentUsingFunctionRef (at **)',
275-
);
276-
expect(ref).not.toHaveBeenCalled();
277-
278-
// No additional warnings should be logged
279-
const container = document.createElement('div');
280-
const root = ReactDOMClient.createRoot(container);
281-
await act(() => {
282-
root.render(<ParentUsingFunctionRef />);
283-
});
284-
});
285-
286-
// @gate !enableRefAsProp || !__DEV__
287-
it('deduplicates ref warnings based on element or owner', async () => {
288-
// When owner uses JSX, we can use exact line location to dedupe warnings
289-
class AnonymousParentUsingJSX extends React.Component {
290-
render() {
291-
return <FunctionComponent name="A" ref={() => {}} />;
292-
}
293-
}
294-
295-
let instance1;
296-
297-
await expect(async () => {
298-
const container = document.createElement('div');
299-
const root = ReactDOMClient.createRoot(container);
300-
301-
await act(() => {
302-
root.render(
303-
<AnonymousParentUsingJSX ref={current => (instance1 = current)} />,
304-
);
305-
});
306-
}).toErrorDev('Function components cannot be given refs.');
307-
// Should be deduped (offending element is on the same line):
308-
instance1.forceUpdate();
309-
// Should also be deduped (offending element is on the same line):
310-
let container = document.createElement('div');
311-
let root = ReactDOMClient.createRoot(container);
312-
await act(() => {
313-
root.render(<AnonymousParentUsingJSX />);
314-
});
315-
316-
// When owner doesn't use JSX, and is anonymous, we warn once per internal instance.
317-
class AnonymousParentNotUsingJSX extends React.Component {
318-
render() {
319-
return React.createElement(FunctionComponent, {
320-
name: 'A',
321-
ref: () => {},
322-
});
323-
}
324-
}
325-
326-
let instance2;
327-
await expect(async () => {
328-
container = document.createElement('div');
329-
root = ReactDOMClient.createRoot(container);
330-
await act(() => {
331-
root.render(
332-
<AnonymousParentNotUsingJSX ref={current => (instance2 = current)} />,
333-
);
334-
});
335-
}).toErrorDev('Function components cannot be given refs.');
336-
// Should be deduped (same internal instance, no additional warnings)
337-
instance2.forceUpdate();
338-
// Could not be differentiated (since owner is anonymous and no source location)
339-
container = document.createElement('div');
340-
root = ReactDOMClient.createRoot(container);
341-
await act(() => {
342-
root.render(<AnonymousParentNotUsingJSX />);
343-
});
344-
345-
// When owner doesn't use JSX, but is named, we warn once per owner name
346-
class NamedParentNotUsingJSX extends React.Component {
347-
render() {
348-
return React.createElement(FunctionComponent, {
349-
name: 'A',
350-
ref: () => {},
351-
});
352-
}
353-
}
354-
let instance3;
355-
await expect(async () => {
356-
container = document.createElement('div');
357-
root = ReactDOMClient.createRoot(container);
358-
await act(() => {
359-
root.render(
360-
<NamedParentNotUsingJSX ref={current => (instance3 = current)} />,
361-
);
362-
});
363-
}).toErrorDev('Function components cannot be given refs.');
364-
// Should be deduped (same owner name, no additional warnings):
365-
instance3.forceUpdate();
366-
// Should also be deduped (same owner name, no additional warnings):
367-
container = document.createElement('div');
368-
root = ReactDOMClient.createRoot(container);
369-
await act(() => {
370-
root.render(<NamedParentNotUsingJSX />);
371-
});
372-
});
373-
374-
// This guards against a regression caused by clearing the current debug fiber.
375-
// https://github.com/facebook/react/issues/10831
376-
// @gate !disableLegacyContext || !__DEV__
377-
// @gate !enableRefAsProp || !__DEV__
378-
it('should warn when giving a function ref with context', async () => {
379-
function Child() {
380-
return null;
381-
}
382-
Child.contextTypes = {
383-
foo: PropTypes.string,
384-
};
385-
386-
class Parent extends React.Component {
387-
static childContextTypes = {
388-
foo: PropTypes.string,
389-
};
390-
getChildContext() {
391-
return {
392-
foo: 'bar',
393-
};
394-
}
395-
render() {
396-
return <Child ref={function () {}} />;
397-
}
398-
}
399-
400-
await expect(async () => {
401-
const container = document.createElement('div');
402-
const root = ReactDOMClient.createRoot(container);
403-
await act(() => {
404-
root.render(<Parent />);
405-
});
406-
}).toErrorDev(
407-
'Function components cannot be given refs. ' +
408-
'Attempts to access this ref will fail. ' +
409-
'Did you mean to use React.forwardRef()?\n\n' +
410-
'Check the render method ' +
411-
'of `Parent`.\n' +
412-
' in Child (at **)\n' +
413-
' in Parent (at **)',
414-
);
415-
});
416-
417200
it('should use correct name in key warning', async () => {
418201
function Child() {
419202
return <div>{[<span />]}</div>;

packages/react-dom/src/__tests__/refs-test.js

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -369,24 +369,6 @@ describe('ref swapping', () => {
369369
});
370370
}).rejects.toThrow('Expected ref to be a function');
371371
});
372-
373-
// @gate !enableRefAsProp && www
374-
it('undefined ref on manually inlined React element triggers error', async () => {
375-
const container = document.createElement('div');
376-
const root = ReactDOMClient.createRoot(container);
377-
await expect(async () => {
378-
await act(() => {
379-
root.render({
380-
$$typeof: Symbol.for('react.element'),
381-
type: 'div',
382-
props: {
383-
ref: undefined,
384-
},
385-
key: null,
386-
});
387-
});
388-
}).rejects.toThrow('Expected ref to be a function');
389-
});
390372
});
391373

392374
describe('root level refs', () => {

packages/react-noop-renderer/src/createReactNoop.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,7 @@ import {
3535
ConcurrentRoot,
3636
LegacyRoot,
3737
} from 'react-reconciler/constants';
38-
import {
39-
enableRefAsProp,
40-
disableLegacyMode,
41-
disableStringRefs,
42-
} from 'shared/ReactFeatureFlags';
38+
import {disableLegacyMode, disableStringRefs} from 'shared/ReactFeatureFlags';
4339

4440
import ReactSharedInternals from 'shared/ReactSharedInternals';
4541

@@ -816,7 +812,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
816812
let currentEventPriority = DefaultEventPriority;
817813

818814
function createJSXElementForTestComparison(type, props) {
819-
if (__DEV__ && enableRefAsProp) {
815+
if (__DEV__) {
820816
const element = {
821817
type: type,
822818
$$typeof: REACT_ELEMENT_TYPE,

packages/react-reconciler/src/ReactChildFiber.js

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ import {
4545
} from './ReactWorkTags';
4646
import isArray from 'shared/isArray';
4747
import {
48-
enableRefAsProp,
4948
enableAsyncIterableChildren,
5049
disableLegacyMode,
5150
enableOwnerStacks,
@@ -239,21 +238,6 @@ function validateFragmentProps(
239238
break;
240239
}
241240
}
242-
243-
if (!enableRefAsProp && element.ref !== null) {
244-
if (fiber === null) {
245-
// For unkeyed root fragments there's no Fiber. We create a fake one just for
246-
// error stack handling.
247-
fiber = createFiberFromElement(element, returnFiber.mode, 0);
248-
if (__DEV__) {
249-
fiber._debugInfo = currentDebugInfo;
250-
}
251-
fiber.return = returnFiber;
252-
}
253-
runWithFiberInDEV(fiber, () => {
254-
console.error('Invalid attribute `ref` supplied to `React.Fragment`.');
255-
});
256-
}
257241
}
258242
}
259243

@@ -272,21 +256,13 @@ function coerceRef(
272256
workInProgress: Fiber,
273257
element: ReactElement,
274258
): void {
275-
let ref;
276-
if (enableRefAsProp) {
277-
// TODO: This is a temporary, intermediate step. When enableRefAsProp is on,
278-
// we should resolve the `ref` prop during the begin phase of the component
279-
// it's attached to (HostComponent, ClassComponent, etc).
280-
const refProp = element.props.ref;
281-
ref = refProp !== undefined ? refProp : null;
282-
} else {
283-
// Old behavior.
284-
ref = element.ref;
285-
}
286-
287-
// TODO: If enableRefAsProp is on, we shouldn't use the `ref` field. We
259+
// TODO: This is a temporary, intermediate step. Now that enableRefAsProp is on,
260+
// we should resolve the `ref` prop during the begin phase of the component
261+
// it's attached to (HostComponent, ClassComponent, etc).
262+
const refProp = element.props.ref;
263+
// TODO: With enableRefAsProp now rolled out, we shouldn't use the `ref` field. We
288264
// should always read the ref from the prop.
289-
workInProgress.ref = ref;
265+
workInProgress.ref = refProp !== undefined ? refProp : null;
290266
}
291267

292268
function throwOnInvalidObjectType(returnFiber: Fiber, newChild: Object) {

0 commit comments

Comments
 (0)