Remove enableRefAsProp feature flag (#30346)

The flag is fully rolled out.
This commit is contained in:
Jan Kassens 2024-11-04 14:30:58 -05:00 committed by GitHub
parent 543eb09321
commit 07aa494432
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 113 additions and 859 deletions

View File

@ -6,7 +6,7 @@
*/
import {REACT_ELEMENT_TYPE, REACT_FRAGMENT_TYPE} from 'shared/ReactSymbols';
import {disableStringRefs, enableRefAsProp} from 'shared/ReactFeatureFlags';
import {disableStringRefs} from 'shared/ReactFeatureFlags';
const {assertConsoleLogsCleared} = require('internal-test-utils/consoleMock');
import isArray from 'shared/isArray';
@ -42,7 +42,7 @@ function assertYieldsWereCleared(root) {
}
function createJSXElementForTestComparison(type, props) {
if (__DEV__ && enableRefAsProp) {
if (__DEV__) {
const element = {
$$typeof: REACT_ELEMENT_TYPE,
type: type,

View File

@ -44,7 +44,6 @@ import {
disableStringRefs,
enableBinaryFlight,
enablePostpone,
enableRefAsProp,
enableFlightReadableStream,
enableOwnerStacks,
enableServerComponentLogs,
@ -676,7 +675,7 @@ function createElement(
| React$Element<any>
| LazyComponent<React$Element<any>, SomeChunk<React$Element<any>>> {
let element: any;
if (__DEV__ && enableRefAsProp) {
if (__DEV__) {
// `ref` is non-enumerable in dev
element = ({
$$typeof: REACT_ELEMENT_TYPE,

View File

@ -868,89 +868,6 @@ describe('Store (legacy)', () => {
`);
});
// TODO: These tests don't work when enableRefAsProp is on because the
// JSX runtime that's injected into the test environment by the compiler
// is not compatible with older versions of React. Need to configure the
// the test environment in such a way that certain test modules like this
// one can use an older transform.
if (!require('shared/ReactFeatureFlags').enableRefAsProp) {
it('should support expanding deep parts of the tree', () => {
const Wrapper = ({forwardedRef}) =>
React.createElement(Nested, {
depth: 3,
forwardedRef: forwardedRef,
});
const Nested = ({depth, forwardedRef}) =>
depth > 0
? React.createElement(Nested, {
depth: depth - 1,
forwardedRef: forwardedRef,
})
: React.createElement('div', {
ref: forwardedRef,
});
let ref = null;
const refSetter = value => {
ref = value;
};
act(() =>
ReactDOM.render(
React.createElement(Wrapper, {
forwardedRef: refSetter,
}),
document.createElement('div'),
),
);
expect(store).toMatchInlineSnapshot(`
[root]
<Wrapper>
`);
const deepestedNodeID = global.agent.getIDForHostInstance(ref);
act(() => store.toggleIsCollapsed(deepestedNodeID, false));
expect(store).toMatchInlineSnapshot(`
[root]
<Wrapper>
<Nested>
<Nested>
<Nested>
<Nested>
<div>
`);
const rootID = store.getElementIDAtIndex(0);
act(() => store.toggleIsCollapsed(rootID, true));
expect(store).toMatchInlineSnapshot(`
[root]
<Wrapper>
`);
act(() => store.toggleIsCollapsed(rootID, false));
expect(store).toMatchInlineSnapshot(`
[root]
<Wrapper>
<Nested>
<Nested>
<Nested>
<Nested>
<div>
`);
const id = store.getElementIDAtIndex(1);
act(() => store.toggleIsCollapsed(id, true));
expect(store).toMatchInlineSnapshot(`
[root]
<Wrapper>
<Nested>
`);
act(() => store.toggleIsCollapsed(id, false));
expect(store).toMatchInlineSnapshot(`
[root]
<Wrapper>
<Nested>
<Nested>
<Nested>
<Nested>
<div>
`);
});
}
it('should support reordering of children', () => {
const Root = ({children}) => React.createElement('div', null, children);
const Component = () => React.createElement('div', null);

View File

@ -197,223 +197,6 @@ describe('ReactFunctionComponent', () => {
.rejects.toThrowError();
});
// @gate !enableRefAsProp || !__DEV__
it('should warn when given a string ref', async () => {
function Indirection(props) {
return <div>{props.children}</div>;
}
class ParentUsingStringRef extends React.Component {
render() {
return (
<Indirection>
<FunctionComponent name="A" ref="stateless" />
</Indirection>
);
}
}
await expect(async () => {
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<ParentUsingStringRef />);
});
}).toErrorDev(
'Function components cannot be given refs. ' +
'Attempts to access this ref will fail. ' +
'Did you mean to use React.forwardRef()?\n\n' +
'Check the render method ' +
'of `ParentUsingStringRef`.\n' +
' in FunctionComponent (at **)\n' +
' in div (at **)\n' +
' in Indirection (at **)\n' +
' in ParentUsingStringRef (at **)',
);
// No additional warnings should be logged
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<ParentUsingStringRef />);
});
});
// @gate !enableRefAsProp || !__DEV__
it('should warn when given a function ref', async () => {
function Indirection(props) {
return <div>{props.children}</div>;
}
const ref = jest.fn();
class ParentUsingFunctionRef extends React.Component {
render() {
return (
<Indirection>
<FunctionComponent name="A" ref={ref} />
</Indirection>
);
}
}
await expect(async () => {
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<ParentUsingFunctionRef />);
});
}).toErrorDev(
'Function components cannot be given refs. ' +
'Attempts to access this ref will fail. ' +
'Did you mean to use React.forwardRef()?\n\n' +
'Check the render method ' +
'of `ParentUsingFunctionRef`.\n' +
' in FunctionComponent (at **)\n' +
' in div (at **)\n' +
' in Indirection (at **)\n' +
' in ParentUsingFunctionRef (at **)',
);
expect(ref).not.toHaveBeenCalled();
// No additional warnings should be logged
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<ParentUsingFunctionRef />);
});
});
// @gate !enableRefAsProp || !__DEV__
it('deduplicates ref warnings based on element or owner', async () => {
// When owner uses JSX, we can use exact line location to dedupe warnings
class AnonymousParentUsingJSX extends React.Component {
render() {
return <FunctionComponent name="A" ref={() => {}} />;
}
}
let instance1;
await expect(async () => {
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(
<AnonymousParentUsingJSX ref={current => (instance1 = current)} />,
);
});
}).toErrorDev('Function components cannot be given refs.');
// Should be deduped (offending element is on the same line):
instance1.forceUpdate();
// Should also be deduped (offending element is on the same line):
let container = document.createElement('div');
let root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<AnonymousParentUsingJSX />);
});
// When owner doesn't use JSX, and is anonymous, we warn once per internal instance.
class AnonymousParentNotUsingJSX extends React.Component {
render() {
return React.createElement(FunctionComponent, {
name: 'A',
ref: () => {},
});
}
}
let instance2;
await expect(async () => {
container = document.createElement('div');
root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(
<AnonymousParentNotUsingJSX ref={current => (instance2 = current)} />,
);
});
}).toErrorDev('Function components cannot be given refs.');
// Should be deduped (same internal instance, no additional warnings)
instance2.forceUpdate();
// Could not be differentiated (since owner is anonymous and no source location)
container = document.createElement('div');
root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<AnonymousParentNotUsingJSX />);
});
// When owner doesn't use JSX, but is named, we warn once per owner name
class NamedParentNotUsingJSX extends React.Component {
render() {
return React.createElement(FunctionComponent, {
name: 'A',
ref: () => {},
});
}
}
let instance3;
await expect(async () => {
container = document.createElement('div');
root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(
<NamedParentNotUsingJSX ref={current => (instance3 = current)} />,
);
});
}).toErrorDev('Function components cannot be given refs.');
// Should be deduped (same owner name, no additional warnings):
instance3.forceUpdate();
// Should also be deduped (same owner name, no additional warnings):
container = document.createElement('div');
root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<NamedParentNotUsingJSX />);
});
});
// This guards against a regression caused by clearing the current debug fiber.
// https://github.com/facebook/react/issues/10831
// @gate !disableLegacyContext || !__DEV__
// @gate !enableRefAsProp || !__DEV__
it('should warn when giving a function ref with context', async () => {
function Child() {
return null;
}
Child.contextTypes = {
foo: PropTypes.string,
};
class Parent extends React.Component {
static childContextTypes = {
foo: PropTypes.string,
};
getChildContext() {
return {
foo: 'bar',
};
}
render() {
return <Child ref={function () {}} />;
}
}
await expect(async () => {
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<Parent />);
});
}).toErrorDev(
'Function components cannot be given refs. ' +
'Attempts to access this ref will fail. ' +
'Did you mean to use React.forwardRef()?\n\n' +
'Check the render method ' +
'of `Parent`.\n' +
' in Child (at **)\n' +
' in Parent (at **)',
);
});
it('should use correct name in key warning', async () => {
function Child() {
return <div>{[<span />]}</div>;

View File

@ -369,24 +369,6 @@ describe('ref swapping', () => {
});
}).rejects.toThrow('Expected ref to be a function');
});
// @gate !enableRefAsProp && www
it('undefined ref on manually inlined React element triggers error', async () => {
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await expect(async () => {
await act(() => {
root.render({
$$typeof: Symbol.for('react.element'),
type: 'div',
props: {
ref: undefined,
},
key: null,
});
});
}).rejects.toThrow('Expected ref to be a function');
});
});
describe('root level refs', () => {

View File

@ -35,11 +35,7 @@ import {
ConcurrentRoot,
LegacyRoot,
} from 'react-reconciler/constants';
import {
enableRefAsProp,
disableLegacyMode,
disableStringRefs,
} from 'shared/ReactFeatureFlags';
import {disableLegacyMode, disableStringRefs} from 'shared/ReactFeatureFlags';
import ReactSharedInternals from 'shared/ReactSharedInternals';
import ReactVersion from 'shared/ReactVersion';
@ -833,7 +829,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
let currentEventPriority = DefaultEventPriority;
function createJSXElementForTestComparison(type, props) {
if (__DEV__ && enableRefAsProp) {
if (__DEV__) {
const element = {
type: type,
$$typeof: REACT_ELEMENT_TYPE,

View File

@ -45,7 +45,6 @@ import {
} from './ReactWorkTags';
import isArray from 'shared/isArray';
import {
enableRefAsProp,
enableAsyncIterableChildren,
disableLegacyMode,
enableOwnerStacks,
@ -239,21 +238,6 @@ function validateFragmentProps(
break;
}
}
if (!enableRefAsProp && element.ref !== null) {
if (fiber === null) {
// For unkeyed root fragments there's no Fiber. We create a fake one just for
// error stack handling.
fiber = createFiberFromElement(element, returnFiber.mode, 0);
if (__DEV__) {
fiber._debugInfo = currentDebugInfo;
}
fiber.return = returnFiber;
}
runWithFiberInDEV(fiber, () => {
console.error('Invalid attribute `ref` supplied to `React.Fragment`.');
});
}
}
}
@ -266,27 +250,14 @@ function unwrapThenable<T>(thenable: Thenable<T>): T {
return trackUsedThenable(thenableState, thenable, index);
}
function coerceRef(
returnFiber: Fiber,
current: Fiber | null,
workInProgress: Fiber,
element: ReactElement,
): void {
let ref;
if (enableRefAsProp) {
// TODO: This is a temporary, intermediate step. When enableRefAsProp is on,
// we should resolve the `ref` prop during the begin phase of the component
// it's attached to (HostComponent, ClassComponent, etc).
const refProp = element.props.ref;
ref = refProp !== undefined ? refProp : null;
} else {
// Old behavior.
ref = element.ref;
}
// TODO: If enableRefAsProp is on, we shouldn't use the `ref` field. We
function coerceRef(workInProgress: Fiber, element: ReactElement): void {
// TODO: This is a temporary, intermediate step. Now that enableRefAsProp is on,
// we should resolve the `ref` prop during the begin phase of the component
// it's attached to (HostComponent, ClassComponent, etc).
const refProp = element.props.ref;
// TODO: With enableRefAsProp now rolled out, we shouldn't use the `ref` field. We
// should always read the ref from the prop.
workInProgress.ref = ref;
workInProgress.ref = refProp !== undefined ? refProp : null;
}
function throwOnInvalidObjectType(returnFiber: Fiber, newChild: Object) {
@ -569,7 +540,7 @@ function createChildReconciler(
) {
// Move based on index
const existing = useFiber(current, element.props);
coerceRef(returnFiber, current, existing, element);
coerceRef(existing, element);
existing.return = returnFiber;
if (__DEV__) {
existing._debugOwner = element._owner;
@ -580,7 +551,7 @@ function createChildReconciler(
}
// Insert
const created = createFiberFromElement(element, returnFiber.mode, lanes);
coerceRef(returnFiber, current, created, element);
coerceRef(created, element);
created.return = returnFiber;
if (__DEV__) {
created._debugInfo = currentDebugInfo;
@ -693,7 +664,7 @@ function createChildReconciler(
returnFiber.mode,
lanes,
);
coerceRef(returnFiber, null, created, newChild);
coerceRef(created, newChild);
created.return = returnFiber;
if (__DEV__) {
const prevDebugInfo = pushDebugInfo(newChild._debugInfo);
@ -1684,7 +1655,7 @@ function createChildReconciler(
) {
deleteRemainingChildren(returnFiber, child.sibling);
const existing = useFiber(child, element.props);
coerceRef(returnFiber, child, existing, element);
coerceRef(existing, element);
existing.return = returnFiber;
if (__DEV__) {
existing._debugOwner = element._owner;
@ -1722,7 +1693,7 @@ function createChildReconciler(
return created;
} else {
const created = createFiberFromElement(element, returnFiber.mode, lanes);
coerceRef(returnFiber, currentFirstChild, created, element);
coerceRef(created, element);
created.return = returnFiber;
if (__DEV__) {
created._debugInfo = currentDebugInfo;

View File

@ -108,7 +108,6 @@ import {
enableAsyncActions,
enablePostpone,
enableRenderableContext,
enableRefAsProp,
disableLegacyMode,
disableDefaultPropsExceptForClasses,
disableStringRefs,
@ -125,10 +124,7 @@ import {
REACT_MEMO_TYPE,
getIteratorFn,
} from 'shared/ReactSymbols';
import {
getCurrentFiberOwnerNameInDevOrNull,
setCurrentFiber,
} from './ReactCurrentFiber';
import {setCurrentFiber} from './ReactCurrentFiber';
import {
resolveFunctionForHotReloading,
resolveForwardRefForHotReloading,
@ -319,7 +315,6 @@ let didWarnAboutBadClass;
let didWarnAboutContextTypeOnFunctionComponent;
let didWarnAboutContextTypes;
let didWarnAboutGetDerivedStateOnFunctionComponent;
let didWarnAboutFunctionRefs;
export let didWarnAboutReassigningProps: boolean;
let didWarnAboutRevealOrder;
let didWarnAboutTailOptions;
@ -330,7 +325,6 @@ if (__DEV__) {
didWarnAboutContextTypeOnFunctionComponent = ({}: {[string]: boolean});
didWarnAboutContextTypes = ({}: {[string]: boolean});
didWarnAboutGetDerivedStateOnFunctionComponent = ({}: {[string]: boolean});
didWarnAboutFunctionRefs = ({}: {[string]: boolean});
didWarnAboutReassigningProps = false;
didWarnAboutRevealOrder = ({}: {[empty]: boolean});
didWarnAboutTailOptions = ({}: {[string]: boolean});
@ -416,7 +410,7 @@ function updateForwardRef(
const ref = workInProgress.ref;
let propsWithoutRef;
if (enableRefAsProp && 'ref' in nextProps) {
if ('ref' in nextProps) {
// `ref` is just a prop now, but `forwardRef` expects it to not appear in
// the props object. This used to happen in the JSX runtime, but now we do
// it here.
@ -1954,25 +1948,6 @@ function validateFunctionComponentInDev(workInProgress: Fiber, Component: any) {
Component.displayName || Component.name || 'Component',
);
}
if (!enableRefAsProp && workInProgress.ref !== null) {
let info = '';
const componentName = getComponentNameFromType(Component) || 'Unknown';
const ownerName = getCurrentFiberOwnerNameInDevOrNull();
if (ownerName) {
info += '\n\nCheck the render method of `' + ownerName + '`.';
}
const warningKey = componentName + '|' + (ownerName || '');
if (!didWarnAboutFunctionRefs[warningKey]) {
didWarnAboutFunctionRefs[warningKey] = true;
console.error(
'Function components cannot be given refs. ' +
'Attempts to access this ref will fail. ' +
'Did you mean to use React.forwardRef()?%s',
info,
);
}
}
if (
!disableDefaultPropsExceptForClasses &&

View File

@ -23,7 +23,6 @@ import {
enableDebugTracing,
enableSchedulingProfiler,
enableLazyContextPropagation,
enableRefAsProp,
disableDefaultPropsExceptForClasses,
} from 'shared/ReactFeatureFlags';
import ReactStrictModeWarnings from './ReactStrictModeWarnings';
@ -1252,14 +1251,12 @@ export function resolveClassComponentProps(
): Object {
let newProps = baseProps;
if (enableRefAsProp) {
// Remove ref from the props object, if it exists.
if ('ref' in baseProps) {
newProps = ({}: any);
for (const propName in baseProps) {
if (propName !== 'ref') {
newProps[propName] = baseProps[propName];
}
// Remove ref from the props object, if it exists.
if ('ref' in baseProps) {
newProps = ({}: any);
for (const propName in baseProps) {
if (propName !== 'ref') {
newProps[propName] = baseProps[propName];
}
}
}

View File

@ -85,7 +85,6 @@ describe('ReactFiberRefs', () => {
expect(ref2.current).not.toBe(null);
});
// @gate enableRefAsProp
// @gate !disableStringRefs
it('string ref props are converted to function refs', async () => {
let refProp;
@ -105,7 +104,7 @@ describe('ReactFiberRefs', () => {
const root = ReactNoop.createRoot();
await act(() => root.render(<Owner />));
// When string refs aren't disabled, and enableRefAsProp is on, string refs
// When string refs aren't disabled, string refs
// the receiving component receives a callback ref, not the original string.
// This behavior should never be shipped to open source; it's only here to
// allow Meta to keep using string refs temporarily while they finish

View File

@ -1299,20 +1299,7 @@ describe('ReactIncrementalSideEffects', () => {
ReactNoop.render(<Foo show={true} />);
if (gate(flags => flags.enableRefAsProp)) {
await waitForAll([]);
} else {
await expect(async () => await waitForAll([])).toErrorDev(
'Function components cannot be given refs. ' +
'Attempts to access this ref will fail. ' +
'Did you mean to use React.forwardRef()?\n\n' +
'Check the render method ' +
'of `Foo`.\n' +
' in FunctionComponent (at **)\n' +
' in div (at **)\n' +
' in Foo (at **)',
);
}
await waitForAll([]);
expect(ops).toEqual([
classInstance,

View File

@ -1236,30 +1236,6 @@ describe('ReactLazy', () => {
expect(root).toMatchRenderedOutput('2');
});
// @gate !enableRefAsProp || !__DEV__
it('warns about ref on functions for lazy-loaded components', async () => {
const Foo = props => <div />;
const LazyFoo = lazy(() => {
return fakeImport(Foo);
});
const ref = React.createRef();
ReactTestRenderer.create(
<Suspense fallback={<Text text="Loading..." />}>
<LazyFoo ref={ref} />
</Suspense>,
{
unstable_isConcurrent: true,
},
);
await waitForAll(['Loading...']);
await resolveFakeImport(Foo);
await expect(async () => {
await waitForAll([]);
}).toErrorDev('Function components cannot be given refs');
});
it('should error with a component stack naming the resolved component', async () => {
let componentStackMessage;

View File

@ -44,43 +44,6 @@ describe('memo', () => {
return {default: result};
}
// @gate !enableRefAsProp || !__DEV__
it('warns when giving a ref (simple)', async () => {
// This test lives outside sharedTests because the wrappers don't forward
// refs properly, and they end up affecting the current owner which is used
// by the warning (making the messages not line up).
function App() {
return null;
}
App = React.memo(App);
function Outer() {
return <App ref={() => {}} />;
}
ReactNoop.render(<Outer />);
await expect(async () => await waitForAll([])).toErrorDev([
'Function components cannot be given refs. Attempts to access ' +
'this ref will fail.',
]);
});
// @gate !enableRefAsProp || !__DEV__
it('warns when giving a ref (complex)', async () => {
function App() {
return null;
}
// A custom compare function means this won't use SimpleMemoComponent (as of this writing)
// SimpleMemoComponent is unobservable tho, so we can't check :)
App = React.memo(App, () => false);
function Outer() {
return <App ref={() => {}} />;
}
ReactNoop.render(<Outer />);
await expect(async () => await waitForAll([])).toErrorDev([
'Function components cannot be given refs. Attempts to access ' +
'this ref will fail.',
]);
});
// Tests should run against both the lazy and non-lazy versions of `memo`.
// To make the tests work for both versions, we wrap the non-lazy version in
// a lazy function component.

View File

@ -160,7 +160,6 @@ import {
enablePostpone,
enableHalt,
enableRenderableContext,
enableRefAsProp,
disableDefaultPropsExceptForClasses,
enableAsyncIterableChildren,
disableStringRefs,
@ -1671,14 +1670,12 @@ export function resolveClassComponentProps(
): Object {
let newProps = baseProps;
if (enableRefAsProp) {
// Remove ref from the props object, if it exists.
if ('ref' in baseProps) {
newProps = ({}: any);
for (const propName in baseProps) {
if (propName !== 'ref') {
newProps[propName] = baseProps[propName];
}
// Remove ref from the props object, if it exists.
if ('ref' in baseProps) {
newProps = ({}: any);
for (const propName in baseProps) {
if (propName !== 'ref') {
newProps[propName] = baseProps[propName];
}
}
}
@ -1973,7 +1970,7 @@ function renderForwardRef(
ref: any,
): void {
let propsWithoutRef;
if (enableRefAsProp && 'ref' in props) {
if ('ref' in props) {
// `ref` is just a prop now, but `forwardRef` expects it to not appear in
// the props object. This used to happen in the JSX runtime, but now we do
// it here.
@ -2595,16 +2592,10 @@ function retryNode(request: Request, task: Task): void {
const key = element.key;
const props = element.props;
let ref;
if (enableRefAsProp) {
// TODO: This is a temporary, intermediate step. Once the feature
// flag is removed, we should get the ref off the props object right
// before using it.
const refProp = props.ref;
ref = refProp !== undefined ? refProp : null;
} else {
ref = element.ref;
}
// TODO: We should get the ref off the props object right before using
// it.
const refProp = props.ref;
const ref = refProp !== undefined ? refProp : null;
const debugTask: null | ConsoleTask =
__DEV__ && enableOwnerStacks ? task.debugTask : null;

View File

@ -18,7 +18,6 @@ import {
enablePostpone,
enableHalt,
enableTaint,
enableRefAsProp,
enableServerComponentLogs,
enableOwnerStacks,
} from 'shared/ReactFeatureFlags';
@ -2512,16 +2511,10 @@ function renderModelDestructive(
}
const props = element.props;
let ref;
if (enableRefAsProp) {
// TODO: This is a temporary, intermediate step. Once the feature
// flag is removed, we should get the ref off the props object right
// before using it.
const refProp = props.ref;
ref = refProp !== undefined ? refProp : null;
} else {
ref = element.ref;
}
// TODO: We should get the ref off the props object right before using
// it.
const refProp = props.ref;
const ref = refProp !== undefined ? refProp : null;
// Attempt to render the Server Component.

View File

@ -386,39 +386,6 @@ describe('ReactTestRenderer', () => {
expect(log).toEqual([null]);
});
// @gate !enableRefAsProp || !__DEV__
it('warns correctly for refs on SFCs', async () => {
function Bar() {
return <div>Hello, world</div>;
}
class Foo extends React.Component {
fooRef = React.createRef();
render() {
return <Bar ref={this.fooRef} />;
}
}
class Baz extends React.Component {
bazRef = React.createRef();
render() {
return <div ref={this.bazRef} />;
}
}
await act(() => {
ReactTestRenderer.create(<Baz />);
});
await expect(async () => {
await act(() => {
ReactTestRenderer.create(<Foo />);
});
}).toErrorDev(
'Function components cannot be given refs. Attempts ' +
'to access this ref will fail. ' +
'Did you mean to use React.forwardRef()?\n' +
' in Bar (at **)\n' +
' in Foo (at **)',
);
});
it('allows an optional createNodeMock function', async () => {
const mockDivInstance = {appendChild: () => {}};
const mockInputInstance = {focus: () => {}};
@ -1226,11 +1193,9 @@ describe('ReactTestRenderer', () => {
{
instance: null,
nodeType: 'host',
props: gate(flags => flags.enableRefAsProp)
? {
ref: refFn,
}
: {},
props: {
ref: refFn,
},
rendered: [],
type: 'span',
},

View File

@ -37,11 +37,7 @@ describe('ReactCreateElement', () => {
const element = React.createElement(ComponentClass);
expect(element.type).toBe(ComponentClass);
expect(element.key).toBe(null);
if (gate(flags => flags.enableRefAsProp)) {
expect(element.ref).toBe(null);
} else {
expect(element.ref).toBe(null);
}
expect(element.ref).toBe(null);
if (__DEV__) {
expect(Object.isFrozen(element)).toBe(true);
expect(Object.isFrozen(element.props)).toBe(true);
@ -90,45 +86,11 @@ describe('ReactCreateElement', () => {
);
});
// @gate !enableRefAsProp || !__DEV__
it('should warn when `ref` is being accessed', async () => {
class Child extends React.Component {
render() {
return React.createElement('div', null, this.props.ref);
}
}
class Parent extends React.Component {
render() {
return React.createElement(
'div',
null,
React.createElement(Child, {ref: React.createRef()}),
);
}
}
const root = ReactDOMClient.createRoot(document.createElement('div'));
await expect(async () => {
await act(() => {
root.render(React.createElement(Parent));
});
}).toErrorDev(
'Child: `ref` is not a prop. Trying to access it will result ' +
'in `undefined` being returned. If you need to access the same ' +
'value within the child component, you should pass it as a different ' +
'prop. (https://react.dev/link/special-props)',
);
});
it('allows a string to be passed as the type', () => {
const element = React.createElement('div');
expect(element.type).toBe('div');
expect(element.key).toBe(null);
if (gate(flags => flags.enableRefAsProp)) {
expect(element.ref).toBe(null);
} else {
expect(element.ref).toBe(null);
}
expect(element.ref).toBe(null);
if (__DEV__) {
expect(Object.isFrozen(element)).toBe(true);
expect(Object.isFrozen(element.props)).toBe(true);
@ -179,20 +141,13 @@ describe('ReactCreateElement', () => {
foo: '56',
});
expect(element.type).toBe(ComponentClass);
if (gate(flags => flags.enableRefAsProp)) {
expect(() => expect(element.ref).toBe(ref)).toErrorDev(
'Accessing element.ref was removed in React 19',
{withoutStack: true},
);
const expectation = {foo: '56', ref};
Object.freeze(expectation);
expect(element.props).toEqual(expectation);
} else {
const expectation = {foo: '56'};
Object.freeze(expectation);
expect(element.props).toEqual(expectation);
expect(element.ref).toBe(ref);
}
expect(() => expect(element.ref).toBe(ref)).toErrorDev(
'Accessing element.ref was removed in React 19',
{withoutStack: true},
);
const expectation = {foo: '56', ref};
Object.freeze(expectation);
expect(element.props).toEqual(expectation);
});
it('extracts null key', () => {
@ -218,11 +173,7 @@ describe('ReactCreateElement', () => {
const element = React.createElement(ComponentClass, props);
expect(element.type).toBe(ComponentClass);
expect(element.key).toBe(null);
if (gate(flags => flags.enableRefAsProp)) {
expect(element.ref).toBe(null);
} else {
expect(element.ref).toBe(null);
}
expect(element.ref).toBe(null);
if (__DEV__) {
expect(Object.isFrozen(element)).toBe(true);
expect(Object.isFrozen(element.props)).toBe(true);
@ -234,11 +185,7 @@ describe('ReactCreateElement', () => {
const elementA = React.createElement('div');
const elementB = React.createElement('div', elementA.props);
expect(elementB.key).toBe(null);
if (gate(flags => flags.enableRefAsProp)) {
expect(elementB.ref).toBe(null);
} else {
expect(elementB.ref).toBe(null);
}
expect(elementB.ref).toBe(null);
});
it('coerces the key to a string', () => {
@ -248,11 +195,7 @@ describe('ReactCreateElement', () => {
});
expect(element.type).toBe(ComponentClass);
expect(element.key).toBe('12');
if (gate(flags => flags.enableRefAsProp)) {
expect(element.ref).toBe(null);
} else {
expect(element.ref).toBe(null);
}
expect(element.ref).toBe(null);
if (__DEV__) {
expect(Object.isFrozen(element)).toBe(true);
expect(Object.isFrozen(element.props)).toBe(true);

View File

@ -212,11 +212,7 @@ describe('ReactElementClone', () => {
ref: this.xyzRef,
});
expect(clone.key).toBe('xyz');
if (gate(flags => flags.enableRefAsProp)) {
expect(clone.props.ref).toBe(this.xyzRef);
} else {
expect(clone.ref).toBe(this.xyzRef);
}
expect(clone.props.ref).toBe(this.xyzRef);
return <div>{clone}</div>;
}
}
@ -274,17 +270,13 @@ describe('ReactElementClone', () => {
const root = ReactDOMClient.createRoot(document.createElement('div'));
await act(() => root.render(<Grandparent />));
if (gate(flags => flags.enableRefAsProp && flags.disableStringRefs)) {
if (gate(flags => flags.disableStringRefs)) {
expect(component.childRef).toEqual({current: null});
expect(component.parentRef.current.xyzRef.current.tagName).toBe('SPAN');
} else if (
gate(flags => !flags.enableRefAsProp && !flags.disableStringRefs)
) {
} else if (gate(flags => false)) {
expect(component.childRef).toEqual({current: null});
expect(component.parentRef.current.xyzRef.current.tagName).toBe('SPAN');
} else if (
gate(flags => flags.enableRefAsProp && !flags.disableStringRefs)
) {
} else if (gate(flags => !flags.disableStringRefs)) {
expect(component.childRef).toEqual({current: null});
expect(component.parentRef.current.xyzRef.current.tagName).toBe('SPAN');
} else {
@ -397,11 +389,7 @@ describe('ReactElementClone', () => {
const elementA = React.createElement('div');
const elementB = React.cloneElement(elementA, elementA.props);
expect(elementB.key).toBe(null);
if (gate(flags => flags.enableRefAsProp)) {
expect(elementB.ref).toBe(null);
} else {
expect(elementB.ref).toBe(null);
}
expect(elementB.ref).toBe(null);
});
it('should ignore undefined key and ref', () => {
@ -418,21 +406,17 @@ describe('ReactElementClone', () => {
const clone = React.cloneElement(element, props);
expect(clone.type).toBe(ComponentClass);
expect(clone.key).toBe('12');
if (gate(flags => flags.enableRefAsProp && flags.disableStringRefs)) {
if (gate(flags => flags.disableStringRefs)) {
expect(clone.props.ref).toBe('34');
expect(() => expect(clone.ref).toBe('34')).toErrorDev(
'Accessing element.ref was removed in React 19',
{withoutStack: true},
);
expect(clone.props).toEqual({foo: 'ef', ref: '34'});
} else if (
gate(flags => !flags.enableRefAsProp && !flags.disableStringRefs)
) {
} else if (gate(flags => false)) {
expect(clone.ref).toBe(element.ref);
expect(clone.props).toEqual({foo: 'ef'});
} else if (
gate(flags => flags.enableRefAsProp && !flags.disableStringRefs)
) {
} else if (gate(flags => !flags.disableStringRefs)) {
expect(() => {
expect(clone.ref).toBe(element.ref);
}).toErrorDev('Accessing element.ref was removed in React 19', {
@ -462,14 +446,8 @@ describe('ReactElementClone', () => {
const clone = React.cloneElement(element, props);
expect(clone.type).toBe(ComponentClass);
expect(clone.key).toBe('null');
if (gate(flags => flags.enableRefAsProp)) {
expect(clone.ref).toBe(null);
expect(clone.props).toEqual({foo: 'ef', ref: null});
} else {
expect(clone.ref).toBe(null);
expect(clone.props).toEqual({foo: 'ef'});
}
expect(clone.ref).toBe(null);
expect(clone.props).toEqual({foo: 'ef', ref: null});
if (__DEV__) {
expect(Object.isFrozen(element)).toBe(true);
expect(Object.isFrozen(element.props)).toBe(true);

View File

@ -248,23 +248,13 @@ describe('ReactJSXElementValidator', () => {
}
}
if (gate(flags => flags.enableRefAsProp)) {
await expect(async () => {
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<Foo />);
});
}).toErrorDev('Invalid prop `ref` supplied to `React.Fragment`.');
} else {
await expect(async () => {
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<Foo />);
});
}).toErrorDev('Invalid attribute `ref` supplied to `React.Fragment`.');
}
await expect(async () => {
const container = document.createElement('div');
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(<Foo />);
});
}).toErrorDev('Invalid prop `ref` supplied to `React.Fragment`.');
});
it('does not warn for fragments of multiple elements without keys', async () => {

View File

@ -244,34 +244,6 @@ describe('ReactJSXRuntime', () => {
);
});
// @gate !enableRefAsProp || !__DEV__
it('should warn when `ref` is being accessed', async () => {
const container = document.createElement('div');
class Child extends React.Component {
render() {
return JSXRuntime.jsx('div', {children: this.props.ref});
}
}
class Parent extends React.Component {
render() {
return JSXRuntime.jsx('div', {
children: JSXRuntime.jsx(Child, {ref: React.createRef()}),
});
}
}
await expect(async () => {
const root = ReactDOMClient.createRoot(container);
await act(() => {
root.render(JSXRuntime.jsx(Parent, {}));
});
}).toErrorDev(
'Child: `ref` is not a prop. Trying to access it will result ' +
'in `undefined` being returned. If you need to access the same ' +
'value within the child component, you should pass it as a different ' +
'prop. (https://react.dev/link/special-props)',
);
});
it('should warn when unkeyed children are passed to jsx', async () => {
const container = document.createElement('div');
@ -377,7 +349,6 @@ describe('ReactJSXRuntime', () => {
expect(didCall).toBe(false);
});
// @gate enableRefAsProp
it('does not clone props object if key and ref is not spread', async () => {
const config = {
foo: 'foo',

View File

@ -55,11 +55,7 @@ describe('ReactJSXTransformIntegration', () => {
const element = <Component />;
expect(element.type).toBe(Component);
expect(element.key).toBe(null);
if (gate(flags => flags.enableRefAsProp)) {
expect(element.ref).toBe(null);
} else {
expect(element.ref).toBe(null);
}
expect(element.ref).toBe(null);
const expectation = {};
Object.freeze(expectation);
expect(element.props).toEqual(expectation);
@ -69,11 +65,7 @@ describe('ReactJSXTransformIntegration', () => {
const element = <div />;
expect(element.type).toBe('div');
expect(element.key).toBe(null);
if (gate(flags => flags.enableRefAsProp)) {
expect(element.ref).toBe(null);
} else {
expect(element.ref).toBe(null);
}
expect(element.ref).toBe(null);
const expectation = {};
Object.freeze(expectation);
expect(element.props).toEqual(expectation);
@ -84,11 +76,7 @@ describe('ReactJSXTransformIntegration', () => {
const element = <TagName />;
expect(element.type).toBe('div');
expect(element.key).toBe(null);
if (gate(flags => flags.enableRefAsProp)) {
expect(element.ref).toBe(null);
} else {
expect(element.ref).toBe(null);
}
expect(element.ref).toBe(null);
const expectation = {};
Object.freeze(expectation);
expect(element.props).toEqual(expectation);
@ -124,31 +112,20 @@ describe('ReactJSXTransformIntegration', () => {
const ref = React.createRef();
const element = <Component ref={ref} foo="56" />;
expect(element.type).toBe(Component);
if (gate(flags => flags.enableRefAsProp)) {
expect(() => expect(element.ref).toBe(ref)).toErrorDev(
'Accessing element.ref was removed in React 19',
{withoutStack: true},
);
const expectation = {foo: '56', ref};
Object.freeze(expectation);
expect(element.props).toEqual(expectation);
} else {
const expectation = {foo: '56'};
Object.freeze(expectation);
expect(element.props).toEqual(expectation);
expect(element.ref).toBe(ref);
}
expect(() => expect(element.ref).toBe(ref)).toErrorDev(
'Accessing element.ref was removed in React 19',
{withoutStack: true},
);
const expectation = {foo: '56', ref};
Object.freeze(expectation);
expect(element.props).toEqual(expectation);
});
it('coerces the key to a string', () => {
const element = <Component key={12} foo="56" />;
expect(element.type).toBe(Component);
expect(element.key).toBe('12');
if (gate(flags => flags.enableRefAsProp)) {
expect(element.ref).toBe(null);
} else {
expect(element.ref).toBe(null);
}
expect(element.ref).toBe(null);
const expectation = {foo: '56'};
Object.freeze(expectation);
expect(element.props).toEqual(expectation);

View File

@ -20,7 +20,6 @@ import isValidElementType from 'shared/isValidElementType';
import isArray from 'shared/isArray';
import {describeUnknownElementTypeFrameInDEV} from 'shared/ReactComponentStackFrame';
import {
enableRefAsProp,
disableStringRefs,
disableDefaultPropsExceptForClasses,
enableOwnerStacks,
@ -72,7 +71,6 @@ function getOwner() {
}
let specialPropKeyWarningShown;
let specialPropRefWarningShown;
let didWarnAboutStringRefs;
let didWarnAboutElementRef;
let didWarnAboutOldJSXRuntime;
@ -82,7 +80,7 @@ if (__DEV__ || enableLogStringRefsProd) {
didWarnAboutElementRef = {};
}
const enableFastJSXWithoutStringRefs = enableRefAsProp && disableStringRefs;
const enableFastJSXWithoutStringRefs = disableStringRefs;
function hasValidRef(config) {
if (__DEV__) {
@ -159,30 +157,6 @@ function defineKeyPropWarningGetter(props, displayName) {
}
}
function defineRefPropWarningGetter(props, displayName) {
if (!enableRefAsProp) {
if (__DEV__) {
const warnAboutAccessingRef = function () {
if (!specialPropRefWarningShown) {
specialPropRefWarningShown = true;
console.error(
'%s: `ref` is not a prop. Trying to access it will result ' +
'in `undefined` being returned. If you need to access the same ' +
'value within the child component, you should pass it as a different ' +
'prop. (https://react.dev/link/special-props)',
displayName,
);
}
};
warnAboutAccessingRef.isReactWarning = true;
Object.defineProperty(props, 'ref', {
get: warnAboutAccessingRef,
configurable: true,
});
}
}
}
function elementRefGetterWithDeprecationWarning() {
if (__DEV__) {
const componentName = getComponentNameFromType(this.type);
@ -225,7 +199,6 @@ function elementRefGetterWithDeprecationWarning() {
function ReactElement(
type,
key,
_ref,
self,
source,
owner,
@ -233,24 +206,18 @@ function ReactElement(
debugStack,
debugTask,
) {
let ref;
if (enableRefAsProp) {
// When enableRefAsProp is on, ignore whatever was passed as the ref
// argument and treat `props.ref` as the source of truth. The only thing we
// use this for is `element.ref`, which will log a deprecation warning on
// access. In the next release, we can remove `element.ref` as well as the
// `ref` argument.
const refProp = props.ref;
// Ignore whatever was passed as the ref argument and treat `props.ref` as
// the source of truth. The only thing we use this for is `element.ref`,
// which will log a deprecation warning on access. In the next release, we
// can remove `element.ref` as well as the `ref` argument.
const refProp = props.ref;
// An undefined `element.ref` is coerced to `null` for
// backwards compatibility.
ref = refProp !== undefined ? refProp : null;
} else {
ref = _ref;
}
// An undefined `element.ref` is coerced to `null` for
// backwards compatibility.
const ref = refProp !== undefined ? refProp : null;
let element;
if (__DEV__ && enableRefAsProp) {
if (__DEV__) {
// In dev, make `ref` a non-enumerable property with a warning. It's non-
// enumerable so that test matchers and serializers don't access it and
// trigger the warning.
@ -380,7 +347,6 @@ function ReactElement(
*/
export function jsxProd(type, config, maybeKey) {
let key = null;
let ref = null;
// Currently, key can be spread in as a prop. This causes a potential
// issue if key is also explicitly declared (ie. <div {...props} key="Hi" />
@ -402,19 +368,9 @@ export function jsxProd(type, config, maybeKey) {
key = '' + config.key;
}
if (hasValidRef(config)) {
if (!enableRefAsProp) {
ref = config.ref;
if (!disableStringRefs) {
ref = coerceStringRef(ref, getOwner(), type);
}
}
}
let props;
if (
(enableFastJSXWithoutStringRefs ||
(enableRefAsProp && !('ref' in config))) &&
(enableFastJSXWithoutStringRefs || !('ref' in config)) &&
!('key' in config)
) {
// If key was not spread in, we can reuse the original props object. This
@ -434,8 +390,8 @@ export function jsxProd(type, config, maybeKey) {
props = {};
for (const propName in config) {
// Skip over reserved prop names
if (propName !== 'key' && (enableRefAsProp || propName !== 'ref')) {
if (enableRefAsProp && !disableStringRefs && propName === 'ref') {
if (propName !== 'key') {
if (!disableStringRefs && propName === 'ref') {
props.ref = coerceStringRef(config[propName], getOwner(), type);
} else {
props[propName] = config[propName];
@ -459,7 +415,6 @@ export function jsxProd(type, config, maybeKey) {
return ReactElement(
type,
key,
ref,
undefined,
undefined,
getOwner(),
@ -662,7 +617,6 @@ function jsxDEVImpl(
}
let key = null;
let ref = null;
// Currently, key can be spread in as a prop. This causes a potential
// issue if key is also explicitly declared (ie. <div {...props} key="Hi" />
@ -684,22 +638,15 @@ function jsxDEVImpl(
key = '' + config.key;
}
if (hasValidRef(config)) {
if (!enableRefAsProp) {
ref = config.ref;
if (!disableStringRefs) {
ref = coerceStringRef(ref, getOwner(), type);
}
}
if (!disableStringRefs) {
if (!disableStringRefs) {
if (hasValidRef(config)) {
warnIfStringRefCannotBeAutoConverted(config, self);
}
}
let props;
if (
(enableFastJSXWithoutStringRefs ||
(enableRefAsProp && !('ref' in config))) &&
(enableFastJSXWithoutStringRefs || !('ref' in config)) &&
!('key' in config)
) {
// If key was not spread in, we can reuse the original props object. This
@ -719,8 +666,8 @@ function jsxDEVImpl(
props = {};
for (const propName in config) {
// Skip over reserved prop names
if (propName !== 'key' && (enableRefAsProp || propName !== 'ref')) {
if (enableRefAsProp && !disableStringRefs && propName === 'ref') {
if (propName !== 'key') {
if (!disableStringRefs && propName === 'ref') {
props.ref = coerceStringRef(config[propName], getOwner(), type);
} else {
props[propName] = config[propName];
@ -741,23 +688,17 @@ function jsxDEVImpl(
}
}
if (key || (!enableRefAsProp && ref)) {
if (key) {
const displayName =
typeof type === 'function'
? type.displayName || type.name || 'Unknown'
: type;
if (key) {
defineKeyPropWarningGetter(props, displayName);
}
if (!enableRefAsProp && ref) {
defineRefPropWarningGetter(props, displayName);
}
defineKeyPropWarningGetter(props, displayName);
}
return ReactElement(
type,
key,
ref,
self,
source,
getOwner(),
@ -838,7 +779,6 @@ export function createElement(type, config, children) {
const props = {};
let key = null;
let ref = null;
if (config != null) {
if (__DEV__) {
@ -861,15 +801,8 @@ export function createElement(type, config, children) {
}
}
if (hasValidRef(config)) {
if (!enableRefAsProp) {
ref = config.ref;
if (!disableStringRefs) {
ref = coerceStringRef(ref, getOwner(), type);
}
}
if (__DEV__ && !disableStringRefs) {
if (__DEV__ && !disableStringRefs) {
if (hasValidRef(config)) {
warnIfStringRefCannotBeAutoConverted(config, config.__self);
}
}
@ -886,7 +819,6 @@ export function createElement(type, config, children) {
hasOwnProperty.call(config, propName) &&
// Skip over reserved prop names
propName !== 'key' &&
(enableRefAsProp || propName !== 'ref') &&
// Even though we don't use these anymore in the runtime, we don't want
// them to appear as props, so in createElement we filter them out.
// We don't have to do this in the jsx() runtime because the jsx()
@ -894,7 +826,7 @@ export function createElement(type, config, children) {
propName !== '__self' &&
propName !== '__source'
) {
if (enableRefAsProp && !disableStringRefs && propName === 'ref') {
if (!disableStringRefs && propName === 'ref') {
props.ref = coerceStringRef(config[propName], getOwner(), type);
} else {
props[propName] = config[propName];
@ -931,24 +863,18 @@ export function createElement(type, config, children) {
}
}
if (__DEV__) {
if (key || (!enableRefAsProp && ref)) {
if (key) {
const displayName =
typeof type === 'function'
? type.displayName || type.name || 'Unknown'
: type;
if (key) {
defineKeyPropWarningGetter(props, displayName);
}
if (!enableRefAsProp && ref) {
defineRefPropWarningGetter(props, displayName);
}
defineKeyPropWarningGetter(props, displayName);
}
}
return ReactElement(
type,
key,
ref,
undefined,
undefined,
getOwner(),
@ -962,9 +888,6 @@ export function cloneAndReplaceKey(oldElement, newKey) {
const clonedElement = ReactElement(
oldElement.type,
newKey,
// When enableRefAsProp is on, this argument is ignored. This check only
// exists to avoid the `ref` access warning.
enableRefAsProp ? null : oldElement.ref,
undefined,
undefined,
!__DEV__ && disableStringRefs ? undefined : oldElement._owner,
@ -997,7 +920,6 @@ export function cloneElement(element, config, children) {
// Reserved names are extracted
let key = element.key;
let ref = enableRefAsProp ? null : element.ref;
// Owner will be preserved, unless ref is overridden
let owner = !__DEV__ && disableStringRefs ? undefined : element._owner;
@ -1005,13 +927,6 @@ export function cloneElement(element, config, children) {
if (config != null) {
if (hasValidRef(config)) {
owner = __DEV__ || !disableStringRefs ? getOwner() : undefined;
if (!enableRefAsProp) {
// Silently steal the ref from the parent.
ref = config.ref;
if (!disableStringRefs) {
ref = coerceStringRef(ref, owner, element.type);
}
}
}
if (hasValidKey(config)) {
if (__DEV__) {
@ -1034,7 +949,6 @@ export function cloneElement(element, config, children) {
hasOwnProperty.call(config, propName) &&
// Skip over reserved prop names
propName !== 'key' &&
(enableRefAsProp || propName !== 'ref') &&
// ...and maybe these, too, though we currently rely on them for
// warnings and debug information in dev. Need to decide if we're OK
// with dropping them. In the jsx() runtime it's not an issue because
@ -1046,7 +960,7 @@ export function cloneElement(element, config, children) {
// Undefined `ref` is ignored by cloneElement. We treat it the same as
// if the property were missing. This is mostly for
// backwards compatibility.
!(enableRefAsProp && propName === 'ref' && config.ref === undefined)
!(propName === 'ref' && config.ref === undefined)
) {
if (
!disableDefaultPropsExceptForClasses &&
@ -1056,7 +970,7 @@ export function cloneElement(element, config, children) {
// Resolve default props
props[propName] = defaultProps[propName];
} else {
if (enableRefAsProp && !disableStringRefs && propName === 'ref') {
if (!disableStringRefs && propName === 'ref') {
props.ref = coerceStringRef(config[propName], owner, element.type);
} else {
props[propName] = config[propName];
@ -1082,7 +996,6 @@ export function cloneElement(element, config, children) {
const clonedElement = ReactElement(
element.type,
key,
ref,
undefined,
undefined,
owner,

View File

@ -208,13 +208,8 @@ export const enableFilterEmptyStringAttributesDOM = true;
// Disabled caching behavior of `react/cache` in client runtimes.
export const disableClientCache = true;
// Subtle breaking changes to JSX runtime to make it faster, like passing `ref`
// as a normal prop instead of stripping it from the props object.
// Passes `ref` as a normal prop instead of stripping it from the props object
// during element creation.
export const enableRefAsProp = true;
export const disableStringRefs = true;
/**
* If set to a function, the function will be called with the component name
* and ref string.

View File

@ -73,7 +73,6 @@ export const enableProfilerCommitHooks = __PROFILE__;
export const enableProfilerNestedUpdatePhase = __PROFILE__;
export const enableProfilerTimer = __PROFILE__;
export const enableReactTestRendererWarning = false;
export const enableRefAsProp = true;
export const enableRenderableContext = true;
export const enableRetryLaneExpiration = false;
export const enableSchedulingProfiler = __PROFILE__;

View File

@ -63,7 +63,6 @@ export const enableOwnerStacks = false;
export const enablePersistedModeClonedFlag = false;
export const enablePostpone = false;
export const enableReactTestRendererWarning = false;
export const enableRefAsProp = true;
export const enableRenderableContext = true;
export const enableRetryLaneExpiration = false;
export const enableSchedulingProfiler = __PROFILE__;

View File

@ -91,7 +91,6 @@ export const enableSiblingPrerendering = false;
// We really need to get rid of this whole module. Any test renderer specific
// flags should be handled by the Fiber config.
// const __NEXT_MAJOR__ = __EXPERIMENTAL__;
export const enableRefAsProp = true;
export const disableStringRefs = true;
export const disableLegacyMode = true;
export const disableLegacyContext = true;

View File

@ -56,7 +56,6 @@ export const enableProfilerCommitHooks = __PROFILE__;
export const enableProfilerNestedUpdatePhase = __PROFILE__;
export const enableProfilerTimer = __PROFILE__;
export const enableReactTestRendererWarning = false;
export const enableRefAsProp = true;
export const enableRenderableContext = true;
export const enableRetryLaneExpiration = false;
export const enableSchedulingProfiler = __PROFILE__;

View File

@ -83,7 +83,6 @@ export const disableClientCache = true;
export const enableServerComponentLogs = true;
export const enableInfiniteRenderLoopDetection = false;
export const enableRefAsProp = true;
export const disableStringRefs = false;
export const enableReactTestRendererWarning = false;

View File

@ -101,8 +101,6 @@ export const enableLegacyHidden = true;
export const enableComponentStackLocations = true;
export const enableRefAsProp = true;
export const disableTextareaChildren = __EXPERIMENTAL__;
export const consoleManagedByDevToolsDuringStrictMode = true;