mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 12:20:20 +01:00
Remove enableRefAsProp feature flag (#30346)
The flag is fully rolled out.
This commit is contained in:
parent
543eb09321
commit
07aa494432
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {REACT_ELEMENT_TYPE, REACT_FRAGMENT_TYPE} from 'shared/ReactSymbols';
|
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');
|
const {assertConsoleLogsCleared} = require('internal-test-utils/consoleMock');
|
||||||
|
|
||||||
import isArray from 'shared/isArray';
|
import isArray from 'shared/isArray';
|
||||||
|
|
@ -42,7 +42,7 @@ function assertYieldsWereCleared(root) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function createJSXElementForTestComparison(type, props) {
|
function createJSXElementForTestComparison(type, props) {
|
||||||
if (__DEV__ && enableRefAsProp) {
|
if (__DEV__) {
|
||||||
const element = {
|
const element = {
|
||||||
$$typeof: REACT_ELEMENT_TYPE,
|
$$typeof: REACT_ELEMENT_TYPE,
|
||||||
type: type,
|
type: type,
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,6 @@ import {
|
||||||
disableStringRefs,
|
disableStringRefs,
|
||||||
enableBinaryFlight,
|
enableBinaryFlight,
|
||||||
enablePostpone,
|
enablePostpone,
|
||||||
enableRefAsProp,
|
|
||||||
enableFlightReadableStream,
|
enableFlightReadableStream,
|
||||||
enableOwnerStacks,
|
enableOwnerStacks,
|
||||||
enableServerComponentLogs,
|
enableServerComponentLogs,
|
||||||
|
|
@ -676,7 +675,7 @@ function createElement(
|
||||||
| React$Element<any>
|
| React$Element<any>
|
||||||
| LazyComponent<React$Element<any>, SomeChunk<React$Element<any>>> {
|
| LazyComponent<React$Element<any>, SomeChunk<React$Element<any>>> {
|
||||||
let element: any;
|
let element: any;
|
||||||
if (__DEV__ && enableRefAsProp) {
|
if (__DEV__) {
|
||||||
// `ref` is non-enumerable in dev
|
// `ref` is non-enumerable in dev
|
||||||
element = ({
|
element = ({
|
||||||
$$typeof: REACT_ELEMENT_TYPE,
|
$$typeof: REACT_ELEMENT_TYPE,
|
||||||
|
|
|
||||||
|
|
@ -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', () => {
|
it('should support reordering of children', () => {
|
||||||
const Root = ({children}) => React.createElement('div', null, children);
|
const Root = ({children}) => React.createElement('div', null, children);
|
||||||
const Component = () => React.createElement('div', null);
|
const Component = () => React.createElement('div', null);
|
||||||
|
|
|
||||||
|
|
@ -197,223 +197,6 @@ describe('ReactFunctionComponent', () => {
|
||||||
.rejects.toThrowError();
|
.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 () => {
|
it('should use correct name in key warning', async () => {
|
||||||
function Child() {
|
function Child() {
|
||||||
return <div>{[<span />]}</div>;
|
return <div>{[<span />]}</div>;
|
||||||
|
|
|
||||||
18
packages/react-dom/src/__tests__/refs-test.js
vendored
18
packages/react-dom/src/__tests__/refs-test.js
vendored
|
|
@ -369,24 +369,6 @@ describe('ref swapping', () => {
|
||||||
});
|
});
|
||||||
}).rejects.toThrow('Expected ref to be a function');
|
}).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', () => {
|
describe('root level refs', () => {
|
||||||
|
|
|
||||||
|
|
@ -35,11 +35,7 @@ import {
|
||||||
ConcurrentRoot,
|
ConcurrentRoot,
|
||||||
LegacyRoot,
|
LegacyRoot,
|
||||||
} from 'react-reconciler/constants';
|
} from 'react-reconciler/constants';
|
||||||
import {
|
import {disableLegacyMode, disableStringRefs} from 'shared/ReactFeatureFlags';
|
||||||
enableRefAsProp,
|
|
||||||
disableLegacyMode,
|
|
||||||
disableStringRefs,
|
|
||||||
} from 'shared/ReactFeatureFlags';
|
|
||||||
|
|
||||||
import ReactSharedInternals from 'shared/ReactSharedInternals';
|
import ReactSharedInternals from 'shared/ReactSharedInternals';
|
||||||
import ReactVersion from 'shared/ReactVersion';
|
import ReactVersion from 'shared/ReactVersion';
|
||||||
|
|
@ -833,7 +829,7 @@ function createReactNoop(reconciler: Function, useMutation: boolean) {
|
||||||
let currentEventPriority = DefaultEventPriority;
|
let currentEventPriority = DefaultEventPriority;
|
||||||
|
|
||||||
function createJSXElementForTestComparison(type, props) {
|
function createJSXElementForTestComparison(type, props) {
|
||||||
if (__DEV__ && enableRefAsProp) {
|
if (__DEV__) {
|
||||||
const element = {
|
const element = {
|
||||||
type: type,
|
type: type,
|
||||||
$$typeof: REACT_ELEMENT_TYPE,
|
$$typeof: REACT_ELEMENT_TYPE,
|
||||||
|
|
|
||||||
53
packages/react-reconciler/src/ReactChildFiber.js
vendored
53
packages/react-reconciler/src/ReactChildFiber.js
vendored
|
|
@ -45,7 +45,6 @@ import {
|
||||||
} from './ReactWorkTags';
|
} from './ReactWorkTags';
|
||||||
import isArray from 'shared/isArray';
|
import isArray from 'shared/isArray';
|
||||||
import {
|
import {
|
||||||
enableRefAsProp,
|
|
||||||
enableAsyncIterableChildren,
|
enableAsyncIterableChildren,
|
||||||
disableLegacyMode,
|
disableLegacyMode,
|
||||||
enableOwnerStacks,
|
enableOwnerStacks,
|
||||||
|
|
@ -239,21 +238,6 @@ function validateFragmentProps(
|
||||||
break;
|
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);
|
return trackUsedThenable(thenableState, thenable, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
function coerceRef(
|
function coerceRef(workInProgress: Fiber, element: ReactElement): void {
|
||||||
returnFiber: Fiber,
|
// TODO: This is a temporary, intermediate step. Now that enableRefAsProp is on,
|
||||||
current: Fiber | null,
|
// we should resolve the `ref` prop during the begin phase of the component
|
||||||
workInProgress: Fiber,
|
// it's attached to (HostComponent, ClassComponent, etc).
|
||||||
element: ReactElement,
|
const refProp = element.props.ref;
|
||||||
): void {
|
// TODO: With enableRefAsProp now rolled out, we shouldn't use the `ref` field. We
|
||||||
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
|
|
||||||
// should always read the ref from the prop.
|
// should always read the ref from the prop.
|
||||||
workInProgress.ref = ref;
|
workInProgress.ref = refProp !== undefined ? refProp : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function throwOnInvalidObjectType(returnFiber: Fiber, newChild: Object) {
|
function throwOnInvalidObjectType(returnFiber: Fiber, newChild: Object) {
|
||||||
|
|
@ -569,7 +540,7 @@ function createChildReconciler(
|
||||||
) {
|
) {
|
||||||
// Move based on index
|
// Move based on index
|
||||||
const existing = useFiber(current, element.props);
|
const existing = useFiber(current, element.props);
|
||||||
coerceRef(returnFiber, current, existing, element);
|
coerceRef(existing, element);
|
||||||
existing.return = returnFiber;
|
existing.return = returnFiber;
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
existing._debugOwner = element._owner;
|
existing._debugOwner = element._owner;
|
||||||
|
|
@ -580,7 +551,7 @@ function createChildReconciler(
|
||||||
}
|
}
|
||||||
// Insert
|
// Insert
|
||||||
const created = createFiberFromElement(element, returnFiber.mode, lanes);
|
const created = createFiberFromElement(element, returnFiber.mode, lanes);
|
||||||
coerceRef(returnFiber, current, created, element);
|
coerceRef(created, element);
|
||||||
created.return = returnFiber;
|
created.return = returnFiber;
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
created._debugInfo = currentDebugInfo;
|
created._debugInfo = currentDebugInfo;
|
||||||
|
|
@ -693,7 +664,7 @@ function createChildReconciler(
|
||||||
returnFiber.mode,
|
returnFiber.mode,
|
||||||
lanes,
|
lanes,
|
||||||
);
|
);
|
||||||
coerceRef(returnFiber, null, created, newChild);
|
coerceRef(created, newChild);
|
||||||
created.return = returnFiber;
|
created.return = returnFiber;
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
const prevDebugInfo = pushDebugInfo(newChild._debugInfo);
|
const prevDebugInfo = pushDebugInfo(newChild._debugInfo);
|
||||||
|
|
@ -1684,7 +1655,7 @@ function createChildReconciler(
|
||||||
) {
|
) {
|
||||||
deleteRemainingChildren(returnFiber, child.sibling);
|
deleteRemainingChildren(returnFiber, child.sibling);
|
||||||
const existing = useFiber(child, element.props);
|
const existing = useFiber(child, element.props);
|
||||||
coerceRef(returnFiber, child, existing, element);
|
coerceRef(existing, element);
|
||||||
existing.return = returnFiber;
|
existing.return = returnFiber;
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
existing._debugOwner = element._owner;
|
existing._debugOwner = element._owner;
|
||||||
|
|
@ -1722,7 +1693,7 @@ function createChildReconciler(
|
||||||
return created;
|
return created;
|
||||||
} else {
|
} else {
|
||||||
const created = createFiberFromElement(element, returnFiber.mode, lanes);
|
const created = createFiberFromElement(element, returnFiber.mode, lanes);
|
||||||
coerceRef(returnFiber, currentFirstChild, created, element);
|
coerceRef(created, element);
|
||||||
created.return = returnFiber;
|
created.return = returnFiber;
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
created._debugInfo = currentDebugInfo;
|
created._debugInfo = currentDebugInfo;
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,6 @@ import {
|
||||||
enableAsyncActions,
|
enableAsyncActions,
|
||||||
enablePostpone,
|
enablePostpone,
|
||||||
enableRenderableContext,
|
enableRenderableContext,
|
||||||
enableRefAsProp,
|
|
||||||
disableLegacyMode,
|
disableLegacyMode,
|
||||||
disableDefaultPropsExceptForClasses,
|
disableDefaultPropsExceptForClasses,
|
||||||
disableStringRefs,
|
disableStringRefs,
|
||||||
|
|
@ -125,10 +124,7 @@ import {
|
||||||
REACT_MEMO_TYPE,
|
REACT_MEMO_TYPE,
|
||||||
getIteratorFn,
|
getIteratorFn,
|
||||||
} from 'shared/ReactSymbols';
|
} from 'shared/ReactSymbols';
|
||||||
import {
|
import {setCurrentFiber} from './ReactCurrentFiber';
|
||||||
getCurrentFiberOwnerNameInDevOrNull,
|
|
||||||
setCurrentFiber,
|
|
||||||
} from './ReactCurrentFiber';
|
|
||||||
import {
|
import {
|
||||||
resolveFunctionForHotReloading,
|
resolveFunctionForHotReloading,
|
||||||
resolveForwardRefForHotReloading,
|
resolveForwardRefForHotReloading,
|
||||||
|
|
@ -319,7 +315,6 @@ let didWarnAboutBadClass;
|
||||||
let didWarnAboutContextTypeOnFunctionComponent;
|
let didWarnAboutContextTypeOnFunctionComponent;
|
||||||
let didWarnAboutContextTypes;
|
let didWarnAboutContextTypes;
|
||||||
let didWarnAboutGetDerivedStateOnFunctionComponent;
|
let didWarnAboutGetDerivedStateOnFunctionComponent;
|
||||||
let didWarnAboutFunctionRefs;
|
|
||||||
export let didWarnAboutReassigningProps: boolean;
|
export let didWarnAboutReassigningProps: boolean;
|
||||||
let didWarnAboutRevealOrder;
|
let didWarnAboutRevealOrder;
|
||||||
let didWarnAboutTailOptions;
|
let didWarnAboutTailOptions;
|
||||||
|
|
@ -330,7 +325,6 @@ if (__DEV__) {
|
||||||
didWarnAboutContextTypeOnFunctionComponent = ({}: {[string]: boolean});
|
didWarnAboutContextTypeOnFunctionComponent = ({}: {[string]: boolean});
|
||||||
didWarnAboutContextTypes = ({}: {[string]: boolean});
|
didWarnAboutContextTypes = ({}: {[string]: boolean});
|
||||||
didWarnAboutGetDerivedStateOnFunctionComponent = ({}: {[string]: boolean});
|
didWarnAboutGetDerivedStateOnFunctionComponent = ({}: {[string]: boolean});
|
||||||
didWarnAboutFunctionRefs = ({}: {[string]: boolean});
|
|
||||||
didWarnAboutReassigningProps = false;
|
didWarnAboutReassigningProps = false;
|
||||||
didWarnAboutRevealOrder = ({}: {[empty]: boolean});
|
didWarnAboutRevealOrder = ({}: {[empty]: boolean});
|
||||||
didWarnAboutTailOptions = ({}: {[string]: boolean});
|
didWarnAboutTailOptions = ({}: {[string]: boolean});
|
||||||
|
|
@ -416,7 +410,7 @@ function updateForwardRef(
|
||||||
const ref = workInProgress.ref;
|
const ref = workInProgress.ref;
|
||||||
|
|
||||||
let propsWithoutRef;
|
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
|
// `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
|
// the props object. This used to happen in the JSX runtime, but now we do
|
||||||
// it here.
|
// it here.
|
||||||
|
|
@ -1954,25 +1948,6 @@ function validateFunctionComponentInDev(workInProgress: Fiber, Component: any) {
|
||||||
Component.displayName || Component.name || 'Component',
|
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 (
|
if (
|
||||||
!disableDefaultPropsExceptForClasses &&
|
!disableDefaultPropsExceptForClasses &&
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ import {
|
||||||
enableDebugTracing,
|
enableDebugTracing,
|
||||||
enableSchedulingProfiler,
|
enableSchedulingProfiler,
|
||||||
enableLazyContextPropagation,
|
enableLazyContextPropagation,
|
||||||
enableRefAsProp,
|
|
||||||
disableDefaultPropsExceptForClasses,
|
disableDefaultPropsExceptForClasses,
|
||||||
} from 'shared/ReactFeatureFlags';
|
} from 'shared/ReactFeatureFlags';
|
||||||
import ReactStrictModeWarnings from './ReactStrictModeWarnings';
|
import ReactStrictModeWarnings from './ReactStrictModeWarnings';
|
||||||
|
|
@ -1252,14 +1251,12 @@ export function resolveClassComponentProps(
|
||||||
): Object {
|
): Object {
|
||||||
let newProps = baseProps;
|
let newProps = baseProps;
|
||||||
|
|
||||||
if (enableRefAsProp) {
|
// Remove ref from the props object, if it exists.
|
||||||
// Remove ref from the props object, if it exists.
|
if ('ref' in baseProps) {
|
||||||
if ('ref' in baseProps) {
|
newProps = ({}: any);
|
||||||
newProps = ({}: any);
|
for (const propName in baseProps) {
|
||||||
for (const propName in baseProps) {
|
if (propName !== 'ref') {
|
||||||
if (propName !== 'ref') {
|
newProps[propName] = baseProps[propName];
|
||||||
newProps[propName] = baseProps[propName];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,6 @@ describe('ReactFiberRefs', () => {
|
||||||
expect(ref2.current).not.toBe(null);
|
expect(ref2.current).not.toBe(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
// @gate enableRefAsProp
|
|
||||||
// @gate !disableStringRefs
|
// @gate !disableStringRefs
|
||||||
it('string ref props are converted to function refs', async () => {
|
it('string ref props are converted to function refs', async () => {
|
||||||
let refProp;
|
let refProp;
|
||||||
|
|
@ -105,7 +104,7 @@ describe('ReactFiberRefs', () => {
|
||||||
const root = ReactNoop.createRoot();
|
const root = ReactNoop.createRoot();
|
||||||
await act(() => root.render(<Owner />));
|
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.
|
// 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
|
// 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
|
// allow Meta to keep using string refs temporarily while they finish
|
||||||
|
|
|
||||||
|
|
@ -1299,20 +1299,7 @@ describe('ReactIncrementalSideEffects', () => {
|
||||||
|
|
||||||
ReactNoop.render(<Foo show={true} />);
|
ReactNoop.render(<Foo show={true} />);
|
||||||
|
|
||||||
if (gate(flags => flags.enableRefAsProp)) {
|
await waitForAll([]);
|
||||||
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 **)',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
expect(ops).toEqual([
|
expect(ops).toEqual([
|
||||||
classInstance,
|
classInstance,
|
||||||
|
|
|
||||||
|
|
@ -1236,30 +1236,6 @@ describe('ReactLazy', () => {
|
||||||
expect(root).toMatchRenderedOutput('2');
|
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 () => {
|
it('should error with a component stack naming the resolved component', async () => {
|
||||||
let componentStackMessage;
|
let componentStackMessage;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,43 +44,6 @@ describe('memo', () => {
|
||||||
return {default: result};
|
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`.
|
// 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
|
// To make the tests work for both versions, we wrap the non-lazy version in
|
||||||
// a lazy function component.
|
// a lazy function component.
|
||||||
|
|
|
||||||
31
packages/react-server/src/ReactFizzServer.js
vendored
31
packages/react-server/src/ReactFizzServer.js
vendored
|
|
@ -160,7 +160,6 @@ import {
|
||||||
enablePostpone,
|
enablePostpone,
|
||||||
enableHalt,
|
enableHalt,
|
||||||
enableRenderableContext,
|
enableRenderableContext,
|
||||||
enableRefAsProp,
|
|
||||||
disableDefaultPropsExceptForClasses,
|
disableDefaultPropsExceptForClasses,
|
||||||
enableAsyncIterableChildren,
|
enableAsyncIterableChildren,
|
||||||
disableStringRefs,
|
disableStringRefs,
|
||||||
|
|
@ -1671,14 +1670,12 @@ export function resolveClassComponentProps(
|
||||||
): Object {
|
): Object {
|
||||||
let newProps = baseProps;
|
let newProps = baseProps;
|
||||||
|
|
||||||
if (enableRefAsProp) {
|
// Remove ref from the props object, if it exists.
|
||||||
// Remove ref from the props object, if it exists.
|
if ('ref' in baseProps) {
|
||||||
if ('ref' in baseProps) {
|
newProps = ({}: any);
|
||||||
newProps = ({}: any);
|
for (const propName in baseProps) {
|
||||||
for (const propName in baseProps) {
|
if (propName !== 'ref') {
|
||||||
if (propName !== 'ref') {
|
newProps[propName] = baseProps[propName];
|
||||||
newProps[propName] = baseProps[propName];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1973,7 +1970,7 @@ function renderForwardRef(
|
||||||
ref: any,
|
ref: any,
|
||||||
): void {
|
): void {
|
||||||
let propsWithoutRef;
|
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
|
// `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
|
// the props object. This used to happen in the JSX runtime, but now we do
|
||||||
// it here.
|
// it here.
|
||||||
|
|
@ -2595,16 +2592,10 @@ function retryNode(request: Request, task: Task): void {
|
||||||
const key = element.key;
|
const key = element.key;
|
||||||
const props = element.props;
|
const props = element.props;
|
||||||
|
|
||||||
let ref;
|
// TODO: We should get the ref off the props object right before using
|
||||||
if (enableRefAsProp) {
|
// it.
|
||||||
// TODO: This is a temporary, intermediate step. Once the feature
|
const refProp = props.ref;
|
||||||
// flag is removed, we should get the ref off the props object right
|
const ref = refProp !== undefined ? refProp : null;
|
||||||
// before using it.
|
|
||||||
const refProp = props.ref;
|
|
||||||
ref = refProp !== undefined ? refProp : null;
|
|
||||||
} else {
|
|
||||||
ref = element.ref;
|
|
||||||
}
|
|
||||||
|
|
||||||
const debugTask: null | ConsoleTask =
|
const debugTask: null | ConsoleTask =
|
||||||
__DEV__ && enableOwnerStacks ? task.debugTask : null;
|
__DEV__ && enableOwnerStacks ? task.debugTask : null;
|
||||||
|
|
|
||||||
15
packages/react-server/src/ReactFlightServer.js
vendored
15
packages/react-server/src/ReactFlightServer.js
vendored
|
|
@ -18,7 +18,6 @@ import {
|
||||||
enablePostpone,
|
enablePostpone,
|
||||||
enableHalt,
|
enableHalt,
|
||||||
enableTaint,
|
enableTaint,
|
||||||
enableRefAsProp,
|
|
||||||
enableServerComponentLogs,
|
enableServerComponentLogs,
|
||||||
enableOwnerStacks,
|
enableOwnerStacks,
|
||||||
} from 'shared/ReactFeatureFlags';
|
} from 'shared/ReactFeatureFlags';
|
||||||
|
|
@ -2512,16 +2511,10 @@ function renderModelDestructive(
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = element.props;
|
const props = element.props;
|
||||||
let ref;
|
// TODO: We should get the ref off the props object right before using
|
||||||
if (enableRefAsProp) {
|
// it.
|
||||||
// TODO: This is a temporary, intermediate step. Once the feature
|
const refProp = props.ref;
|
||||||
// flag is removed, we should get the ref off the props object right
|
const ref = refProp !== undefined ? refProp : null;
|
||||||
// before using it.
|
|
||||||
const refProp = props.ref;
|
|
||||||
ref = refProp !== undefined ? refProp : null;
|
|
||||||
} else {
|
|
||||||
ref = element.ref;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to render the Server Component.
|
// Attempt to render the Server Component.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -386,39 +386,6 @@ describe('ReactTestRenderer', () => {
|
||||||
expect(log).toEqual([null]);
|
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 () => {
|
it('allows an optional createNodeMock function', async () => {
|
||||||
const mockDivInstance = {appendChild: () => {}};
|
const mockDivInstance = {appendChild: () => {}};
|
||||||
const mockInputInstance = {focus: () => {}};
|
const mockInputInstance = {focus: () => {}};
|
||||||
|
|
@ -1226,11 +1193,9 @@ describe('ReactTestRenderer', () => {
|
||||||
{
|
{
|
||||||
instance: null,
|
instance: null,
|
||||||
nodeType: 'host',
|
nodeType: 'host',
|
||||||
props: gate(flags => flags.enableRefAsProp)
|
props: {
|
||||||
? {
|
ref: refFn,
|
||||||
ref: refFn,
|
},
|
||||||
}
|
|
||||||
: {},
|
|
||||||
rendered: [],
|
rendered: [],
|
||||||
type: 'span',
|
type: 'span',
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -37,11 +37,7 @@ describe('ReactCreateElement', () => {
|
||||||
const element = React.createElement(ComponentClass);
|
const element = React.createElement(ComponentClass);
|
||||||
expect(element.type).toBe(ComponentClass);
|
expect(element.type).toBe(ComponentClass);
|
||||||
expect(element.key).toBe(null);
|
expect(element.key).toBe(null);
|
||||||
if (gate(flags => flags.enableRefAsProp)) {
|
expect(element.ref).toBe(null);
|
||||||
expect(element.ref).toBe(null);
|
|
||||||
} else {
|
|
||||||
expect(element.ref).toBe(null);
|
|
||||||
}
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
expect(Object.isFrozen(element)).toBe(true);
|
expect(Object.isFrozen(element)).toBe(true);
|
||||||
expect(Object.isFrozen(element.props)).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', () => {
|
it('allows a string to be passed as the type', () => {
|
||||||
const element = React.createElement('div');
|
const element = React.createElement('div');
|
||||||
expect(element.type).toBe('div');
|
expect(element.type).toBe('div');
|
||||||
expect(element.key).toBe(null);
|
expect(element.key).toBe(null);
|
||||||
if (gate(flags => flags.enableRefAsProp)) {
|
expect(element.ref).toBe(null);
|
||||||
expect(element.ref).toBe(null);
|
|
||||||
} else {
|
|
||||||
expect(element.ref).toBe(null);
|
|
||||||
}
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
expect(Object.isFrozen(element)).toBe(true);
|
expect(Object.isFrozen(element)).toBe(true);
|
||||||
expect(Object.isFrozen(element.props)).toBe(true);
|
expect(Object.isFrozen(element.props)).toBe(true);
|
||||||
|
|
@ -179,20 +141,13 @@ describe('ReactCreateElement', () => {
|
||||||
foo: '56',
|
foo: '56',
|
||||||
});
|
});
|
||||||
expect(element.type).toBe(ComponentClass);
|
expect(element.type).toBe(ComponentClass);
|
||||||
if (gate(flags => flags.enableRefAsProp)) {
|
expect(() => expect(element.ref).toBe(ref)).toErrorDev(
|
||||||
expect(() => expect(element.ref).toBe(ref)).toErrorDev(
|
'Accessing element.ref was removed in React 19',
|
||||||
'Accessing element.ref was removed in React 19',
|
{withoutStack: true},
|
||||||
{withoutStack: true},
|
);
|
||||||
);
|
const expectation = {foo: '56', ref};
|
||||||
const expectation = {foo: '56', ref};
|
Object.freeze(expectation);
|
||||||
Object.freeze(expectation);
|
expect(element.props).toEqual(expectation);
|
||||||
expect(element.props).toEqual(expectation);
|
|
||||||
} else {
|
|
||||||
const expectation = {foo: '56'};
|
|
||||||
Object.freeze(expectation);
|
|
||||||
expect(element.props).toEqual(expectation);
|
|
||||||
expect(element.ref).toBe(ref);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('extracts null key', () => {
|
it('extracts null key', () => {
|
||||||
|
|
@ -218,11 +173,7 @@ describe('ReactCreateElement', () => {
|
||||||
const element = React.createElement(ComponentClass, props);
|
const element = React.createElement(ComponentClass, props);
|
||||||
expect(element.type).toBe(ComponentClass);
|
expect(element.type).toBe(ComponentClass);
|
||||||
expect(element.key).toBe(null);
|
expect(element.key).toBe(null);
|
||||||
if (gate(flags => flags.enableRefAsProp)) {
|
expect(element.ref).toBe(null);
|
||||||
expect(element.ref).toBe(null);
|
|
||||||
} else {
|
|
||||||
expect(element.ref).toBe(null);
|
|
||||||
}
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
expect(Object.isFrozen(element)).toBe(true);
|
expect(Object.isFrozen(element)).toBe(true);
|
||||||
expect(Object.isFrozen(element.props)).toBe(true);
|
expect(Object.isFrozen(element.props)).toBe(true);
|
||||||
|
|
@ -234,11 +185,7 @@ describe('ReactCreateElement', () => {
|
||||||
const elementA = React.createElement('div');
|
const elementA = React.createElement('div');
|
||||||
const elementB = React.createElement('div', elementA.props);
|
const elementB = React.createElement('div', elementA.props);
|
||||||
expect(elementB.key).toBe(null);
|
expect(elementB.key).toBe(null);
|
||||||
if (gate(flags => flags.enableRefAsProp)) {
|
expect(elementB.ref).toBe(null);
|
||||||
expect(elementB.ref).toBe(null);
|
|
||||||
} else {
|
|
||||||
expect(elementB.ref).toBe(null);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('coerces the key to a string', () => {
|
it('coerces the key to a string', () => {
|
||||||
|
|
@ -248,11 +195,7 @@ describe('ReactCreateElement', () => {
|
||||||
});
|
});
|
||||||
expect(element.type).toBe(ComponentClass);
|
expect(element.type).toBe(ComponentClass);
|
||||||
expect(element.key).toBe('12');
|
expect(element.key).toBe('12');
|
||||||
if (gate(flags => flags.enableRefAsProp)) {
|
expect(element.ref).toBe(null);
|
||||||
expect(element.ref).toBe(null);
|
|
||||||
} else {
|
|
||||||
expect(element.ref).toBe(null);
|
|
||||||
}
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
expect(Object.isFrozen(element)).toBe(true);
|
expect(Object.isFrozen(element)).toBe(true);
|
||||||
expect(Object.isFrozen(element.props)).toBe(true);
|
expect(Object.isFrozen(element.props)).toBe(true);
|
||||||
|
|
|
||||||
|
|
@ -212,11 +212,7 @@ describe('ReactElementClone', () => {
|
||||||
ref: this.xyzRef,
|
ref: this.xyzRef,
|
||||||
});
|
});
|
||||||
expect(clone.key).toBe('xyz');
|
expect(clone.key).toBe('xyz');
|
||||||
if (gate(flags => flags.enableRefAsProp)) {
|
expect(clone.props.ref).toBe(this.xyzRef);
|
||||||
expect(clone.props.ref).toBe(this.xyzRef);
|
|
||||||
} else {
|
|
||||||
expect(clone.ref).toBe(this.xyzRef);
|
|
||||||
}
|
|
||||||
return <div>{clone}</div>;
|
return <div>{clone}</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -274,17 +270,13 @@ describe('ReactElementClone', () => {
|
||||||
|
|
||||||
const root = ReactDOMClient.createRoot(document.createElement('div'));
|
const root = ReactDOMClient.createRoot(document.createElement('div'));
|
||||||
await act(() => root.render(<Grandparent />));
|
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.childRef).toEqual({current: null});
|
||||||
expect(component.parentRef.current.xyzRef.current.tagName).toBe('SPAN');
|
expect(component.parentRef.current.xyzRef.current.tagName).toBe('SPAN');
|
||||||
} else if (
|
} else if (gate(flags => false)) {
|
||||||
gate(flags => !flags.enableRefAsProp && !flags.disableStringRefs)
|
|
||||||
) {
|
|
||||||
expect(component.childRef).toEqual({current: null});
|
expect(component.childRef).toEqual({current: null});
|
||||||
expect(component.parentRef.current.xyzRef.current.tagName).toBe('SPAN');
|
expect(component.parentRef.current.xyzRef.current.tagName).toBe('SPAN');
|
||||||
} else if (
|
} else if (gate(flags => !flags.disableStringRefs)) {
|
||||||
gate(flags => flags.enableRefAsProp && !flags.disableStringRefs)
|
|
||||||
) {
|
|
||||||
expect(component.childRef).toEqual({current: null});
|
expect(component.childRef).toEqual({current: null});
|
||||||
expect(component.parentRef.current.xyzRef.current.tagName).toBe('SPAN');
|
expect(component.parentRef.current.xyzRef.current.tagName).toBe('SPAN');
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -397,11 +389,7 @@ describe('ReactElementClone', () => {
|
||||||
const elementA = React.createElement('div');
|
const elementA = React.createElement('div');
|
||||||
const elementB = React.cloneElement(elementA, elementA.props);
|
const elementB = React.cloneElement(elementA, elementA.props);
|
||||||
expect(elementB.key).toBe(null);
|
expect(elementB.key).toBe(null);
|
||||||
if (gate(flags => flags.enableRefAsProp)) {
|
expect(elementB.ref).toBe(null);
|
||||||
expect(elementB.ref).toBe(null);
|
|
||||||
} else {
|
|
||||||
expect(elementB.ref).toBe(null);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should ignore undefined key and ref', () => {
|
it('should ignore undefined key and ref', () => {
|
||||||
|
|
@ -418,21 +406,17 @@ describe('ReactElementClone', () => {
|
||||||
const clone = React.cloneElement(element, props);
|
const clone = React.cloneElement(element, props);
|
||||||
expect(clone.type).toBe(ComponentClass);
|
expect(clone.type).toBe(ComponentClass);
|
||||||
expect(clone.key).toBe('12');
|
expect(clone.key).toBe('12');
|
||||||
if (gate(flags => flags.enableRefAsProp && flags.disableStringRefs)) {
|
if (gate(flags => flags.disableStringRefs)) {
|
||||||
expect(clone.props.ref).toBe('34');
|
expect(clone.props.ref).toBe('34');
|
||||||
expect(() => expect(clone.ref).toBe('34')).toErrorDev(
|
expect(() => expect(clone.ref).toBe('34')).toErrorDev(
|
||||||
'Accessing element.ref was removed in React 19',
|
'Accessing element.ref was removed in React 19',
|
||||||
{withoutStack: true},
|
{withoutStack: true},
|
||||||
);
|
);
|
||||||
expect(clone.props).toEqual({foo: 'ef', ref: '34'});
|
expect(clone.props).toEqual({foo: 'ef', ref: '34'});
|
||||||
} else if (
|
} else if (gate(flags => false)) {
|
||||||
gate(flags => !flags.enableRefAsProp && !flags.disableStringRefs)
|
|
||||||
) {
|
|
||||||
expect(clone.ref).toBe(element.ref);
|
expect(clone.ref).toBe(element.ref);
|
||||||
expect(clone.props).toEqual({foo: 'ef'});
|
expect(clone.props).toEqual({foo: 'ef'});
|
||||||
} else if (
|
} else if (gate(flags => !flags.disableStringRefs)) {
|
||||||
gate(flags => flags.enableRefAsProp && !flags.disableStringRefs)
|
|
||||||
) {
|
|
||||||
expect(() => {
|
expect(() => {
|
||||||
expect(clone.ref).toBe(element.ref);
|
expect(clone.ref).toBe(element.ref);
|
||||||
}).toErrorDev('Accessing element.ref was removed in React 19', {
|
}).toErrorDev('Accessing element.ref was removed in React 19', {
|
||||||
|
|
@ -462,14 +446,8 @@ describe('ReactElementClone', () => {
|
||||||
const clone = React.cloneElement(element, props);
|
const clone = React.cloneElement(element, props);
|
||||||
expect(clone.type).toBe(ComponentClass);
|
expect(clone.type).toBe(ComponentClass);
|
||||||
expect(clone.key).toBe('null');
|
expect(clone.key).toBe('null');
|
||||||
if (gate(flags => flags.enableRefAsProp)) {
|
expect(clone.ref).toBe(null);
|
||||||
expect(clone.ref).toBe(null);
|
expect(clone.props).toEqual({foo: 'ef', ref: null});
|
||||||
expect(clone.props).toEqual({foo: 'ef', ref: null});
|
|
||||||
} else {
|
|
||||||
expect(clone.ref).toBe(null);
|
|
||||||
expect(clone.props).toEqual({foo: 'ef'});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
expect(Object.isFrozen(element)).toBe(true);
|
expect(Object.isFrozen(element)).toBe(true);
|
||||||
expect(Object.isFrozen(element.props)).toBe(true);
|
expect(Object.isFrozen(element.props)).toBe(true);
|
||||||
|
|
|
||||||
|
|
@ -248,23 +248,13 @@ describe('ReactJSXElementValidator', () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gate(flags => flags.enableRefAsProp)) {
|
await expect(async () => {
|
||||||
await expect(async () => {
|
const container = document.createElement('div');
|
||||||
const container = document.createElement('div');
|
const root = ReactDOMClient.createRoot(container);
|
||||||
const root = ReactDOMClient.createRoot(container);
|
await act(() => {
|
||||||
await act(() => {
|
root.render(<Foo />);
|
||||||
root.render(<Foo />);
|
});
|
||||||
});
|
}).toErrorDev('Invalid prop `ref` supplied to `React.Fragment`.');
|
||||||
}).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`.');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not warn for fragments of multiple elements without keys', async () => {
|
it('does not warn for fragments of multiple elements without keys', async () => {
|
||||||
|
|
|
||||||
|
|
@ -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 () => {
|
it('should warn when unkeyed children are passed to jsx', async () => {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
|
|
||||||
|
|
@ -377,7 +349,6 @@ describe('ReactJSXRuntime', () => {
|
||||||
expect(didCall).toBe(false);
|
expect(didCall).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
// @gate enableRefAsProp
|
|
||||||
it('does not clone props object if key and ref is not spread', async () => {
|
it('does not clone props object if key and ref is not spread', async () => {
|
||||||
const config = {
|
const config = {
|
||||||
foo: 'foo',
|
foo: 'foo',
|
||||||
|
|
|
||||||
|
|
@ -55,11 +55,7 @@ describe('ReactJSXTransformIntegration', () => {
|
||||||
const element = <Component />;
|
const element = <Component />;
|
||||||
expect(element.type).toBe(Component);
|
expect(element.type).toBe(Component);
|
||||||
expect(element.key).toBe(null);
|
expect(element.key).toBe(null);
|
||||||
if (gate(flags => flags.enableRefAsProp)) {
|
expect(element.ref).toBe(null);
|
||||||
expect(element.ref).toBe(null);
|
|
||||||
} else {
|
|
||||||
expect(element.ref).toBe(null);
|
|
||||||
}
|
|
||||||
const expectation = {};
|
const expectation = {};
|
||||||
Object.freeze(expectation);
|
Object.freeze(expectation);
|
||||||
expect(element.props).toEqual(expectation);
|
expect(element.props).toEqual(expectation);
|
||||||
|
|
@ -69,11 +65,7 @@ describe('ReactJSXTransformIntegration', () => {
|
||||||
const element = <div />;
|
const element = <div />;
|
||||||
expect(element.type).toBe('div');
|
expect(element.type).toBe('div');
|
||||||
expect(element.key).toBe(null);
|
expect(element.key).toBe(null);
|
||||||
if (gate(flags => flags.enableRefAsProp)) {
|
expect(element.ref).toBe(null);
|
||||||
expect(element.ref).toBe(null);
|
|
||||||
} else {
|
|
||||||
expect(element.ref).toBe(null);
|
|
||||||
}
|
|
||||||
const expectation = {};
|
const expectation = {};
|
||||||
Object.freeze(expectation);
|
Object.freeze(expectation);
|
||||||
expect(element.props).toEqual(expectation);
|
expect(element.props).toEqual(expectation);
|
||||||
|
|
@ -84,11 +76,7 @@ describe('ReactJSXTransformIntegration', () => {
|
||||||
const element = <TagName />;
|
const element = <TagName />;
|
||||||
expect(element.type).toBe('div');
|
expect(element.type).toBe('div');
|
||||||
expect(element.key).toBe(null);
|
expect(element.key).toBe(null);
|
||||||
if (gate(flags => flags.enableRefAsProp)) {
|
expect(element.ref).toBe(null);
|
||||||
expect(element.ref).toBe(null);
|
|
||||||
} else {
|
|
||||||
expect(element.ref).toBe(null);
|
|
||||||
}
|
|
||||||
const expectation = {};
|
const expectation = {};
|
||||||
Object.freeze(expectation);
|
Object.freeze(expectation);
|
||||||
expect(element.props).toEqual(expectation);
|
expect(element.props).toEqual(expectation);
|
||||||
|
|
@ -124,31 +112,20 @@ describe('ReactJSXTransformIntegration', () => {
|
||||||
const ref = React.createRef();
|
const ref = React.createRef();
|
||||||
const element = <Component ref={ref} foo="56" />;
|
const element = <Component ref={ref} foo="56" />;
|
||||||
expect(element.type).toBe(Component);
|
expect(element.type).toBe(Component);
|
||||||
if (gate(flags => flags.enableRefAsProp)) {
|
expect(() => expect(element.ref).toBe(ref)).toErrorDev(
|
||||||
expect(() => expect(element.ref).toBe(ref)).toErrorDev(
|
'Accessing element.ref was removed in React 19',
|
||||||
'Accessing element.ref was removed in React 19',
|
{withoutStack: true},
|
||||||
{withoutStack: true},
|
);
|
||||||
);
|
const expectation = {foo: '56', ref};
|
||||||
const expectation = {foo: '56', ref};
|
Object.freeze(expectation);
|
||||||
Object.freeze(expectation);
|
expect(element.props).toEqual(expectation);
|
||||||
expect(element.props).toEqual(expectation);
|
|
||||||
} else {
|
|
||||||
const expectation = {foo: '56'};
|
|
||||||
Object.freeze(expectation);
|
|
||||||
expect(element.props).toEqual(expectation);
|
|
||||||
expect(element.ref).toBe(ref);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('coerces the key to a string', () => {
|
it('coerces the key to a string', () => {
|
||||||
const element = <Component key={12} foo="56" />;
|
const element = <Component key={12} foo="56" />;
|
||||||
expect(element.type).toBe(Component);
|
expect(element.type).toBe(Component);
|
||||||
expect(element.key).toBe('12');
|
expect(element.key).toBe('12');
|
||||||
if (gate(flags => flags.enableRefAsProp)) {
|
expect(element.ref).toBe(null);
|
||||||
expect(element.ref).toBe(null);
|
|
||||||
} else {
|
|
||||||
expect(element.ref).toBe(null);
|
|
||||||
}
|
|
||||||
const expectation = {foo: '56'};
|
const expectation = {foo: '56'};
|
||||||
Object.freeze(expectation);
|
Object.freeze(expectation);
|
||||||
expect(element.props).toEqual(expectation);
|
expect(element.props).toEqual(expectation);
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ import isValidElementType from 'shared/isValidElementType';
|
||||||
import isArray from 'shared/isArray';
|
import isArray from 'shared/isArray';
|
||||||
import {describeUnknownElementTypeFrameInDEV} from 'shared/ReactComponentStackFrame';
|
import {describeUnknownElementTypeFrameInDEV} from 'shared/ReactComponentStackFrame';
|
||||||
import {
|
import {
|
||||||
enableRefAsProp,
|
|
||||||
disableStringRefs,
|
disableStringRefs,
|
||||||
disableDefaultPropsExceptForClasses,
|
disableDefaultPropsExceptForClasses,
|
||||||
enableOwnerStacks,
|
enableOwnerStacks,
|
||||||
|
|
@ -72,7 +71,6 @@ function getOwner() {
|
||||||
}
|
}
|
||||||
|
|
||||||
let specialPropKeyWarningShown;
|
let specialPropKeyWarningShown;
|
||||||
let specialPropRefWarningShown;
|
|
||||||
let didWarnAboutStringRefs;
|
let didWarnAboutStringRefs;
|
||||||
let didWarnAboutElementRef;
|
let didWarnAboutElementRef;
|
||||||
let didWarnAboutOldJSXRuntime;
|
let didWarnAboutOldJSXRuntime;
|
||||||
|
|
@ -82,7 +80,7 @@ if (__DEV__ || enableLogStringRefsProd) {
|
||||||
didWarnAboutElementRef = {};
|
didWarnAboutElementRef = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const enableFastJSXWithoutStringRefs = enableRefAsProp && disableStringRefs;
|
const enableFastJSXWithoutStringRefs = disableStringRefs;
|
||||||
|
|
||||||
function hasValidRef(config) {
|
function hasValidRef(config) {
|
||||||
if (__DEV__) {
|
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() {
|
function elementRefGetterWithDeprecationWarning() {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
const componentName = getComponentNameFromType(this.type);
|
const componentName = getComponentNameFromType(this.type);
|
||||||
|
|
@ -225,7 +199,6 @@ function elementRefGetterWithDeprecationWarning() {
|
||||||
function ReactElement(
|
function ReactElement(
|
||||||
type,
|
type,
|
||||||
key,
|
key,
|
||||||
_ref,
|
|
||||||
self,
|
self,
|
||||||
source,
|
source,
|
||||||
owner,
|
owner,
|
||||||
|
|
@ -233,24 +206,18 @@ function ReactElement(
|
||||||
debugStack,
|
debugStack,
|
||||||
debugTask,
|
debugTask,
|
||||||
) {
|
) {
|
||||||
let ref;
|
// Ignore whatever was passed as the ref argument and treat `props.ref` as
|
||||||
if (enableRefAsProp) {
|
// the source of truth. The only thing we use this for is `element.ref`,
|
||||||
// When enableRefAsProp is on, ignore whatever was passed as the ref
|
// which will log a deprecation warning on access. In the next release, we
|
||||||
// argument and treat `props.ref` as the source of truth. The only thing we
|
// can remove `element.ref` as well as the `ref` argument.
|
||||||
// use this for is `element.ref`, which will log a deprecation warning on
|
const refProp = props.ref;
|
||||||
// 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
|
// An undefined `element.ref` is coerced to `null` for
|
||||||
// backwards compatibility.
|
// backwards compatibility.
|
||||||
ref = refProp !== undefined ? refProp : null;
|
const ref = refProp !== undefined ? refProp : null;
|
||||||
} else {
|
|
||||||
ref = _ref;
|
|
||||||
}
|
|
||||||
|
|
||||||
let element;
|
let element;
|
||||||
if (__DEV__ && enableRefAsProp) {
|
if (__DEV__) {
|
||||||
// In dev, make `ref` a non-enumerable property with a warning. It's non-
|
// 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
|
// enumerable so that test matchers and serializers don't access it and
|
||||||
// trigger the warning.
|
// trigger the warning.
|
||||||
|
|
@ -380,7 +347,6 @@ function ReactElement(
|
||||||
*/
|
*/
|
||||||
export function jsxProd(type, config, maybeKey) {
|
export function jsxProd(type, config, maybeKey) {
|
||||||
let key = null;
|
let key = null;
|
||||||
let ref = null;
|
|
||||||
|
|
||||||
// Currently, key can be spread in as a prop. This causes a potential
|
// 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" />
|
// 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;
|
key = '' + config.key;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasValidRef(config)) {
|
|
||||||
if (!enableRefAsProp) {
|
|
||||||
ref = config.ref;
|
|
||||||
if (!disableStringRefs) {
|
|
||||||
ref = coerceStringRef(ref, getOwner(), type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let props;
|
let props;
|
||||||
if (
|
if (
|
||||||
(enableFastJSXWithoutStringRefs ||
|
(enableFastJSXWithoutStringRefs || !('ref' in config)) &&
|
||||||
(enableRefAsProp && !('ref' in config))) &&
|
|
||||||
!('key' in config)
|
!('key' in config)
|
||||||
) {
|
) {
|
||||||
// If key was not spread in, we can reuse the original props object. This
|
// 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 = {};
|
props = {};
|
||||||
for (const propName in config) {
|
for (const propName in config) {
|
||||||
// Skip over reserved prop names
|
// Skip over reserved prop names
|
||||||
if (propName !== 'key' && (enableRefAsProp || propName !== 'ref')) {
|
if (propName !== 'key') {
|
||||||
if (enableRefAsProp && !disableStringRefs && propName === 'ref') {
|
if (!disableStringRefs && propName === 'ref') {
|
||||||
props.ref = coerceStringRef(config[propName], getOwner(), type);
|
props.ref = coerceStringRef(config[propName], getOwner(), type);
|
||||||
} else {
|
} else {
|
||||||
props[propName] = config[propName];
|
props[propName] = config[propName];
|
||||||
|
|
@ -459,7 +415,6 @@ export function jsxProd(type, config, maybeKey) {
|
||||||
return ReactElement(
|
return ReactElement(
|
||||||
type,
|
type,
|
||||||
key,
|
key,
|
||||||
ref,
|
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
getOwner(),
|
getOwner(),
|
||||||
|
|
@ -662,7 +617,6 @@ function jsxDEVImpl(
|
||||||
}
|
}
|
||||||
|
|
||||||
let key = null;
|
let key = null;
|
||||||
let ref = null;
|
|
||||||
|
|
||||||
// Currently, key can be spread in as a prop. This causes a potential
|
// 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" />
|
// issue if key is also explicitly declared (ie. <div {...props} key="Hi" />
|
||||||
|
|
@ -684,22 +638,15 @@ function jsxDEVImpl(
|
||||||
key = '' + config.key;
|
key = '' + config.key;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasValidRef(config)) {
|
if (!disableStringRefs) {
|
||||||
if (!enableRefAsProp) {
|
if (hasValidRef(config)) {
|
||||||
ref = config.ref;
|
|
||||||
if (!disableStringRefs) {
|
|
||||||
ref = coerceStringRef(ref, getOwner(), type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!disableStringRefs) {
|
|
||||||
warnIfStringRefCannotBeAutoConverted(config, self);
|
warnIfStringRefCannotBeAutoConverted(config, self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let props;
|
let props;
|
||||||
if (
|
if (
|
||||||
(enableFastJSXWithoutStringRefs ||
|
(enableFastJSXWithoutStringRefs || !('ref' in config)) &&
|
||||||
(enableRefAsProp && !('ref' in config))) &&
|
|
||||||
!('key' in config)
|
!('key' in config)
|
||||||
) {
|
) {
|
||||||
// If key was not spread in, we can reuse the original props object. This
|
// If key was not spread in, we can reuse the original props object. This
|
||||||
|
|
@ -719,8 +666,8 @@ function jsxDEVImpl(
|
||||||
props = {};
|
props = {};
|
||||||
for (const propName in config) {
|
for (const propName in config) {
|
||||||
// Skip over reserved prop names
|
// Skip over reserved prop names
|
||||||
if (propName !== 'key' && (enableRefAsProp || propName !== 'ref')) {
|
if (propName !== 'key') {
|
||||||
if (enableRefAsProp && !disableStringRefs && propName === 'ref') {
|
if (!disableStringRefs && propName === 'ref') {
|
||||||
props.ref = coerceStringRef(config[propName], getOwner(), type);
|
props.ref = coerceStringRef(config[propName], getOwner(), type);
|
||||||
} else {
|
} else {
|
||||||
props[propName] = config[propName];
|
props[propName] = config[propName];
|
||||||
|
|
@ -741,23 +688,17 @@ function jsxDEVImpl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key || (!enableRefAsProp && ref)) {
|
if (key) {
|
||||||
const displayName =
|
const displayName =
|
||||||
typeof type === 'function'
|
typeof type === 'function'
|
||||||
? type.displayName || type.name || 'Unknown'
|
? type.displayName || type.name || 'Unknown'
|
||||||
: type;
|
: type;
|
||||||
if (key) {
|
defineKeyPropWarningGetter(props, displayName);
|
||||||
defineKeyPropWarningGetter(props, displayName);
|
|
||||||
}
|
|
||||||
if (!enableRefAsProp && ref) {
|
|
||||||
defineRefPropWarningGetter(props, displayName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ReactElement(
|
return ReactElement(
|
||||||
type,
|
type,
|
||||||
key,
|
key,
|
||||||
ref,
|
|
||||||
self,
|
self,
|
||||||
source,
|
source,
|
||||||
getOwner(),
|
getOwner(),
|
||||||
|
|
@ -838,7 +779,6 @@ export function createElement(type, config, children) {
|
||||||
const props = {};
|
const props = {};
|
||||||
|
|
||||||
let key = null;
|
let key = null;
|
||||||
let ref = null;
|
|
||||||
|
|
||||||
if (config != null) {
|
if (config != null) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
|
|
@ -861,15 +801,8 @@ export function createElement(type, config, children) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasValidRef(config)) {
|
if (__DEV__ && !disableStringRefs) {
|
||||||
if (!enableRefAsProp) {
|
if (hasValidRef(config)) {
|
||||||
ref = config.ref;
|
|
||||||
if (!disableStringRefs) {
|
|
||||||
ref = coerceStringRef(ref, getOwner(), type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (__DEV__ && !disableStringRefs) {
|
|
||||||
warnIfStringRefCannotBeAutoConverted(config, config.__self);
|
warnIfStringRefCannotBeAutoConverted(config, config.__self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -886,7 +819,6 @@ export function createElement(type, config, children) {
|
||||||
hasOwnProperty.call(config, propName) &&
|
hasOwnProperty.call(config, propName) &&
|
||||||
// Skip over reserved prop names
|
// Skip over reserved prop names
|
||||||
propName !== 'key' &&
|
propName !== 'key' &&
|
||||||
(enableRefAsProp || propName !== 'ref') &&
|
|
||||||
// Even though we don't use these anymore in the runtime, we don't want
|
// 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.
|
// 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()
|
// 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 !== '__self' &&
|
||||||
propName !== '__source'
|
propName !== '__source'
|
||||||
) {
|
) {
|
||||||
if (enableRefAsProp && !disableStringRefs && propName === 'ref') {
|
if (!disableStringRefs && propName === 'ref') {
|
||||||
props.ref = coerceStringRef(config[propName], getOwner(), type);
|
props.ref = coerceStringRef(config[propName], getOwner(), type);
|
||||||
} else {
|
} else {
|
||||||
props[propName] = config[propName];
|
props[propName] = config[propName];
|
||||||
|
|
@ -931,24 +863,18 @@ export function createElement(type, config, children) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
if (key || (!enableRefAsProp && ref)) {
|
if (key) {
|
||||||
const displayName =
|
const displayName =
|
||||||
typeof type === 'function'
|
typeof type === 'function'
|
||||||
? type.displayName || type.name || 'Unknown'
|
? type.displayName || type.name || 'Unknown'
|
||||||
: type;
|
: type;
|
||||||
if (key) {
|
defineKeyPropWarningGetter(props, displayName);
|
||||||
defineKeyPropWarningGetter(props, displayName);
|
|
||||||
}
|
|
||||||
if (!enableRefAsProp && ref) {
|
|
||||||
defineRefPropWarningGetter(props, displayName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ReactElement(
|
return ReactElement(
|
||||||
type,
|
type,
|
||||||
key,
|
key,
|
||||||
ref,
|
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
getOwner(),
|
getOwner(),
|
||||||
|
|
@ -962,9 +888,6 @@ export function cloneAndReplaceKey(oldElement, newKey) {
|
||||||
const clonedElement = ReactElement(
|
const clonedElement = ReactElement(
|
||||||
oldElement.type,
|
oldElement.type,
|
||||||
newKey,
|
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,
|
||||||
undefined,
|
undefined,
|
||||||
!__DEV__ && disableStringRefs ? undefined : oldElement._owner,
|
!__DEV__ && disableStringRefs ? undefined : oldElement._owner,
|
||||||
|
|
@ -997,7 +920,6 @@ export function cloneElement(element, config, children) {
|
||||||
|
|
||||||
// Reserved names are extracted
|
// Reserved names are extracted
|
||||||
let key = element.key;
|
let key = element.key;
|
||||||
let ref = enableRefAsProp ? null : element.ref;
|
|
||||||
|
|
||||||
// Owner will be preserved, unless ref is overridden
|
// Owner will be preserved, unless ref is overridden
|
||||||
let owner = !__DEV__ && disableStringRefs ? undefined : element._owner;
|
let owner = !__DEV__ && disableStringRefs ? undefined : element._owner;
|
||||||
|
|
@ -1005,13 +927,6 @@ export function cloneElement(element, config, children) {
|
||||||
if (config != null) {
|
if (config != null) {
|
||||||
if (hasValidRef(config)) {
|
if (hasValidRef(config)) {
|
||||||
owner = __DEV__ || !disableStringRefs ? getOwner() : undefined;
|
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 (hasValidKey(config)) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
|
|
@ -1034,7 +949,6 @@ export function cloneElement(element, config, children) {
|
||||||
hasOwnProperty.call(config, propName) &&
|
hasOwnProperty.call(config, propName) &&
|
||||||
// Skip over reserved prop names
|
// Skip over reserved prop names
|
||||||
propName !== 'key' &&
|
propName !== 'key' &&
|
||||||
(enableRefAsProp || propName !== 'ref') &&
|
|
||||||
// ...and maybe these, too, though we currently rely on them for
|
// ...and maybe these, too, though we currently rely on them for
|
||||||
// warnings and debug information in dev. Need to decide if we're OK
|
// 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
|
// 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
|
// Undefined `ref` is ignored by cloneElement. We treat it the same as
|
||||||
// if the property were missing. This is mostly for
|
// if the property were missing. This is mostly for
|
||||||
// backwards compatibility.
|
// backwards compatibility.
|
||||||
!(enableRefAsProp && propName === 'ref' && config.ref === undefined)
|
!(propName === 'ref' && config.ref === undefined)
|
||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
!disableDefaultPropsExceptForClasses &&
|
!disableDefaultPropsExceptForClasses &&
|
||||||
|
|
@ -1056,7 +970,7 @@ export function cloneElement(element, config, children) {
|
||||||
// Resolve default props
|
// Resolve default props
|
||||||
props[propName] = defaultProps[propName];
|
props[propName] = defaultProps[propName];
|
||||||
} else {
|
} else {
|
||||||
if (enableRefAsProp && !disableStringRefs && propName === 'ref') {
|
if (!disableStringRefs && propName === 'ref') {
|
||||||
props.ref = coerceStringRef(config[propName], owner, element.type);
|
props.ref = coerceStringRef(config[propName], owner, element.type);
|
||||||
} else {
|
} else {
|
||||||
props[propName] = config[propName];
|
props[propName] = config[propName];
|
||||||
|
|
@ -1082,7 +996,6 @@ export function cloneElement(element, config, children) {
|
||||||
const clonedElement = ReactElement(
|
const clonedElement = ReactElement(
|
||||||
element.type,
|
element.type,
|
||||||
key,
|
key,
|
||||||
ref,
|
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
owner,
|
owner,
|
||||||
|
|
|
||||||
|
|
@ -208,13 +208,8 @@ export const enableFilterEmptyStringAttributesDOM = true;
|
||||||
// Disabled caching behavior of `react/cache` in client runtimes.
|
// Disabled caching behavior of `react/cache` in client runtimes.
|
||||||
export const disableClientCache = true;
|
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;
|
export const disableStringRefs = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If set to a function, the function will be called with the component name
|
* If set to a function, the function will be called with the component name
|
||||||
* and ref string.
|
* and ref string.
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,6 @@ export const enableProfilerCommitHooks = __PROFILE__;
|
||||||
export const enableProfilerNestedUpdatePhase = __PROFILE__;
|
export const enableProfilerNestedUpdatePhase = __PROFILE__;
|
||||||
export const enableProfilerTimer = __PROFILE__;
|
export const enableProfilerTimer = __PROFILE__;
|
||||||
export const enableReactTestRendererWarning = false;
|
export const enableReactTestRendererWarning = false;
|
||||||
export const enableRefAsProp = true;
|
|
||||||
export const enableRenderableContext = true;
|
export const enableRenderableContext = true;
|
||||||
export const enableRetryLaneExpiration = false;
|
export const enableRetryLaneExpiration = false;
|
||||||
export const enableSchedulingProfiler = __PROFILE__;
|
export const enableSchedulingProfiler = __PROFILE__;
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,6 @@ export const enableOwnerStacks = false;
|
||||||
export const enablePersistedModeClonedFlag = false;
|
export const enablePersistedModeClonedFlag = false;
|
||||||
export const enablePostpone = false;
|
export const enablePostpone = false;
|
||||||
export const enableReactTestRendererWarning = false;
|
export const enableReactTestRendererWarning = false;
|
||||||
export const enableRefAsProp = true;
|
|
||||||
export const enableRenderableContext = true;
|
export const enableRenderableContext = true;
|
||||||
export const enableRetryLaneExpiration = false;
|
export const enableRetryLaneExpiration = false;
|
||||||
export const enableSchedulingProfiler = __PROFILE__;
|
export const enableSchedulingProfiler = __PROFILE__;
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,6 @@ export const enableSiblingPrerendering = false;
|
||||||
// We really need to get rid of this whole module. Any test renderer specific
|
// We really need to get rid of this whole module. Any test renderer specific
|
||||||
// flags should be handled by the Fiber config.
|
// flags should be handled by the Fiber config.
|
||||||
// const __NEXT_MAJOR__ = __EXPERIMENTAL__;
|
// const __NEXT_MAJOR__ = __EXPERIMENTAL__;
|
||||||
export const enableRefAsProp = true;
|
|
||||||
export const disableStringRefs = true;
|
export const disableStringRefs = true;
|
||||||
export const disableLegacyMode = true;
|
export const disableLegacyMode = true;
|
||||||
export const disableLegacyContext = true;
|
export const disableLegacyContext = true;
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,6 @@ export const enableProfilerCommitHooks = __PROFILE__;
|
||||||
export const enableProfilerNestedUpdatePhase = __PROFILE__;
|
export const enableProfilerNestedUpdatePhase = __PROFILE__;
|
||||||
export const enableProfilerTimer = __PROFILE__;
|
export const enableProfilerTimer = __PROFILE__;
|
||||||
export const enableReactTestRendererWarning = false;
|
export const enableReactTestRendererWarning = false;
|
||||||
export const enableRefAsProp = true;
|
|
||||||
export const enableRenderableContext = true;
|
export const enableRenderableContext = true;
|
||||||
export const enableRetryLaneExpiration = false;
|
export const enableRetryLaneExpiration = false;
|
||||||
export const enableSchedulingProfiler = __PROFILE__;
|
export const enableSchedulingProfiler = __PROFILE__;
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,6 @@ export const disableClientCache = true;
|
||||||
export const enableServerComponentLogs = true;
|
export const enableServerComponentLogs = true;
|
||||||
export const enableInfiniteRenderLoopDetection = false;
|
export const enableInfiniteRenderLoopDetection = false;
|
||||||
|
|
||||||
export const enableRefAsProp = true;
|
|
||||||
export const disableStringRefs = false;
|
export const disableStringRefs = false;
|
||||||
|
|
||||||
export const enableReactTestRendererWarning = false;
|
export const enableReactTestRendererWarning = false;
|
||||||
|
|
|
||||||
|
|
@ -101,8 +101,6 @@ export const enableLegacyHidden = true;
|
||||||
|
|
||||||
export const enableComponentStackLocations = true;
|
export const enableComponentStackLocations = true;
|
||||||
|
|
||||||
export const enableRefAsProp = true;
|
|
||||||
|
|
||||||
export const disableTextareaChildren = __EXPERIMENTAL__;
|
export const disableTextareaChildren = __EXPERIMENTAL__;
|
||||||
|
|
||||||
export const consoleManagedByDevToolsDuringStrictMode = true;
|
export const consoleManagedByDevToolsDuringStrictMode = true;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user