Skip to content

Commit 6479760

Browse files
committed
Pass ref as normal prop (#28348)
Depends on: - #28317 - #28320 --- Changes the behavior of the JSX runtime to pass through `ref` as a normal prop, rather than plucking it from the props object and storing on the element. This is a breaking change since it changes the type of the receiving component. However, most code is unaffected since it's unlikely that a component would have attempted to access a `ref` prop, since it was not possible to get a reference to one. `forwardRef` _will_ still pluck `ref` from the props object, though, since it's extremely common for users to spread the props object onto the inner component and pass `ref` as a differently named prop. This is for maximum compatibility with existing code — the real impact of this change is that `forwardRef` is no longer required. Currently, refs are resolved during child reconciliation and stored on the fiber. As a result of this change, we can move ref resolution to happen only much later, and only for components that actually use them. Then we can remove the `ref` field from the Fiber type. I have not yet done that in this step, though. DiffTrain build for [fa2f82a](fa2f82a)
1 parent 3f81ef2 commit 6479760

34 files changed

+706
-397
lines changed

compiled/facebook-www/JSXDEVRuntime-dev.classic.js

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,25 +1007,27 @@ if (__DEV__) {
10071007

10081008
function defineRefPropWarningGetter(props, displayName) {
10091009
{
1010-
var warnAboutAccessingRef = function () {
1011-
if (!specialPropRefWarningShown) {
1012-
specialPropRefWarningShown = true;
1010+
{
1011+
var warnAboutAccessingRef = function () {
1012+
if (!specialPropRefWarningShown) {
1013+
specialPropRefWarningShown = true;
10131014

1014-
error(
1015-
"%s: `ref` is not a prop. Trying to access it will result " +
1016-
"in `undefined` being returned. If you need to access the same " +
1017-
"value within the child component, you should pass it as a different " +
1018-
"prop. (https://reactjs.org/link/special-props)",
1019-
displayName
1020-
);
1021-
}
1022-
};
1015+
error(
1016+
"%s: `ref` is not a prop. Trying to access it will result " +
1017+
"in `undefined` being returned. If you need to access the same " +
1018+
"value within the child component, you should pass it as a different " +
1019+
"prop. (https://reactjs.org/link/special-props)",
1020+
displayName
1021+
);
1022+
}
1023+
};
10231024

1024-
warnAboutAccessingRef.isReactWarning = true;
1025-
Object.defineProperty(props, "ref", {
1026-
get: warnAboutAccessingRef,
1027-
configurable: true
1028-
});
1025+
warnAboutAccessingRef.isReactWarning = true;
1026+
Object.defineProperty(props, "ref", {
1027+
get: warnAboutAccessingRef,
1028+
configurable: true
1029+
});
1030+
}
10291031
}
10301032
}
10311033
/**
@@ -1049,18 +1051,30 @@ if (__DEV__) {
10491051
* @internal
10501052
*/
10511053

1052-
function ReactElement(type, key, ref, self, source, owner, props) {
1053-
var element = {
1054-
// This tag allows us to uniquely identify this as a React Element
1055-
$$typeof: REACT_ELEMENT_TYPE,
1056-
// Built-in properties that belong on the element
1057-
type: type,
1058-
key: key,
1059-
ref: ref,
1060-
props: props,
1061-
// Record the component responsible for creating this element.
1062-
_owner: owner
1063-
};
1054+
function ReactElement(type, key, _ref, self, source, owner, props) {
1055+
var ref;
1056+
1057+
{
1058+
ref = _ref;
1059+
}
1060+
1061+
var element;
1062+
1063+
{
1064+
// In prod, `ref` is a regular property. It will be removed in a
1065+
// future release.
1066+
element = {
1067+
// This tag allows us to uniquely identify this as a React Element
1068+
$$typeof: REACT_ELEMENT_TYPE,
1069+
// Built-in properties that belong on the element
1070+
type: type,
1071+
key: key,
1072+
ref: ref,
1073+
props: props,
1074+
// Record the component responsible for creating this element.
1075+
_owner: owner
1076+
};
1077+
}
10641078

10651079
{
10661080
// The validation flag is currently mutative. We put it on
@@ -1246,14 +1260,17 @@ if (__DEV__) {
12461260
}
12471261

12481262
if (hasValidRef(config)) {
1249-
ref = config.ref;
1263+
{
1264+
ref = config.ref;
1265+
}
1266+
12501267
warnIfStringRefCannotBeAutoConverted(config, self);
12511268
} // Remaining properties are added to a new props object
12521269

12531270
for (propName in config) {
12541271
if (
12551272
hasOwnProperty.call(config, propName) && // Skip over reserved prop names
1256-
propName !== "key" && // TODO: `ref` will no longer be reserved in the next major
1273+
propName !== "key" &&
12571274
propName !== "ref"
12581275
) {
12591276
props[propName] = config[propName];
@@ -1494,6 +1511,7 @@ if (__DEV__) {
14941511
*/
14951512

14961513
function validateFragmentProps(fragment) {
1514+
// TODO: Move this to render phase instead of at element creation.
14971515
{
14981516
var keys = Object.keys(fragment.props);
14991517

compiled/facebook-www/JSXDEVRuntime-dev.modern.js

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,25 +1007,27 @@ if (__DEV__) {
10071007

10081008
function defineRefPropWarningGetter(props, displayName) {
10091009
{
1010-
var warnAboutAccessingRef = function () {
1011-
if (!specialPropRefWarningShown) {
1012-
specialPropRefWarningShown = true;
1010+
{
1011+
var warnAboutAccessingRef = function () {
1012+
if (!specialPropRefWarningShown) {
1013+
specialPropRefWarningShown = true;
10131014

1014-
error(
1015-
"%s: `ref` is not a prop. Trying to access it will result " +
1016-
"in `undefined` being returned. If you need to access the same " +
1017-
"value within the child component, you should pass it as a different " +
1018-
"prop. (https://reactjs.org/link/special-props)",
1019-
displayName
1020-
);
1021-
}
1022-
};
1015+
error(
1016+
"%s: `ref` is not a prop. Trying to access it will result " +
1017+
"in `undefined` being returned. If you need to access the same " +
1018+
"value within the child component, you should pass it as a different " +
1019+
"prop. (https://reactjs.org/link/special-props)",
1020+
displayName
1021+
);
1022+
}
1023+
};
10231024

1024-
warnAboutAccessingRef.isReactWarning = true;
1025-
Object.defineProperty(props, "ref", {
1026-
get: warnAboutAccessingRef,
1027-
configurable: true
1028-
});
1025+
warnAboutAccessingRef.isReactWarning = true;
1026+
Object.defineProperty(props, "ref", {
1027+
get: warnAboutAccessingRef,
1028+
configurable: true
1029+
});
1030+
}
10291031
}
10301032
}
10311033
/**
@@ -1049,18 +1051,30 @@ if (__DEV__) {
10491051
* @internal
10501052
*/
10511053

1052-
function ReactElement(type, key, ref, self, source, owner, props) {
1053-
var element = {
1054-
// This tag allows us to uniquely identify this as a React Element
1055-
$$typeof: REACT_ELEMENT_TYPE,
1056-
// Built-in properties that belong on the element
1057-
type: type,
1058-
key: key,
1059-
ref: ref,
1060-
props: props,
1061-
// Record the component responsible for creating this element.
1062-
_owner: owner
1063-
};
1054+
function ReactElement(type, key, _ref, self, source, owner, props) {
1055+
var ref;
1056+
1057+
{
1058+
ref = _ref;
1059+
}
1060+
1061+
var element;
1062+
1063+
{
1064+
// In prod, `ref` is a regular property. It will be removed in a
1065+
// future release.
1066+
element = {
1067+
// This tag allows us to uniquely identify this as a React Element
1068+
$$typeof: REACT_ELEMENT_TYPE,
1069+
// Built-in properties that belong on the element
1070+
type: type,
1071+
key: key,
1072+
ref: ref,
1073+
props: props,
1074+
// Record the component responsible for creating this element.
1075+
_owner: owner
1076+
};
1077+
}
10641078

10651079
{
10661080
// The validation flag is currently mutative. We put it on
@@ -1246,14 +1260,17 @@ if (__DEV__) {
12461260
}
12471261

12481262
if (hasValidRef(config)) {
1249-
ref = config.ref;
1263+
{
1264+
ref = config.ref;
1265+
}
1266+
12501267
warnIfStringRefCannotBeAutoConverted(config, self);
12511268
} // Remaining properties are added to a new props object
12521269

12531270
for (propName in config) {
12541271
if (
12551272
hasOwnProperty.call(config, propName) && // Skip over reserved prop names
1256-
propName !== "key" && // TODO: `ref` will no longer be reserved in the next major
1273+
propName !== "key" &&
12571274
propName !== "ref"
12581275
) {
12591276
props[propName] = config[propName];
@@ -1494,6 +1511,7 @@ if (__DEV__) {
14941511
*/
14951512

14961513
function validateFragmentProps(fragment) {
1514+
// TODO: Move this to render phase instead of at element creation.
14971515
{
14981516
var keys = Object.keys(fragment.props);
14991517

compiled/facebook-www/REVISION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
5fb2c93f3924ba980444da5698f60651b5ef0689
1+
fa2f82addc7c817892c482792f56a35277e8b75a

0 commit comments

Comments
 (0)