Skip to content

Commit

Permalink
Eagerly initialize an mutable object for instance.refs
Browse files Browse the repository at this point in the history
This micro-optimization never made sense and less so now that they're rare.

This still initializes the class with a shared immutable object in the
constructor - which is also what createClass() does.

Then we override it during mount. This is done in case someone messes up
the initialization of the super() constructor for example, which was
more common in polyfills.

This change means that if a ref is initialized during the constructor
itself it wouldn't be lazily initialized but that's not user code that
does it, it's React so that shouldn't happen.
  • Loading branch information
sebmarkbage committed Nov 16, 2022
1 parent e1dd0a2 commit 2976957
Show file tree
Hide file tree
Showing 4 changed files with 4 additions and 28 deletions.
7 changes: 1 addition & 6 deletions packages/react-reconciler/src/ReactChildFiber.new.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ import {
createFiberFromText,
createFiberFromPortal,
} from './ReactFiber.new';
import {emptyRefsObject} from './ReactFiberClassComponent.new';
import {isCompatibleFamilyForHotReloading} from './ReactFiberHotReloading.new';
import {StrictLegacyMode} from './ReactTypeOfMode';
import {getIsHydrating} from './ReactFiberHydrationContext.new';
Expand Down Expand Up @@ -192,11 +191,7 @@ function coerceRef(
return current.ref;
}
const ref = function(value) {
let refs = resolvedInst.refs;
if (refs === emptyRefsObject) {
// This is a lazy pooled frozen object, so we need to initialize.
refs = resolvedInst.refs = {};
}
const refs = resolvedInst.refs;
if (value === null) {
delete refs[stringRef];
} else {
Expand Down
7 changes: 1 addition & 6 deletions packages/react-reconciler/src/ReactChildFiber.old.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ import {
createFiberFromText,
createFiberFromPortal,
} from './ReactFiber.old';
import {emptyRefsObject} from './ReactFiberClassComponent.old';
import {isCompatibleFamilyForHotReloading} from './ReactFiberHotReloading.old';
import {StrictLegacyMode} from './ReactTypeOfMode';
import {getIsHydrating} from './ReactFiberHydrationContext.old';
Expand Down Expand Up @@ -192,11 +191,7 @@ function coerceRef(
return current.ref;
}
const ref = function(value) {
let refs = resolvedInst.refs;
if (refs === emptyRefsObject) {
// This is a lazy pooled frozen object, so we need to initialize.
refs = resolvedInst.refs = {};
}
const refs = resolvedInst.refs;
if (value === null) {
delete refs[stringRef];
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import type {Lanes} from './ReactFiberLane.new';
import type {UpdateQueue} from './ReactFiberClassUpdateQueue.new';
import type {Flags} from './ReactFiberFlags';

import * as React from 'react';
import {
LayoutStatic,
Update,
Expand Down Expand Up @@ -80,12 +79,6 @@ import {

const fakeInternalInstance = {};

// React.Component uses a shared frozen object by default.
// We'll use it to determine whether we need to initialize legacy refs.
export const emptyRefsObject: $FlowFixMe = React.Component
? new React.Component().refs
: {};

let didWarnAboutStateAssignmentForComponent;
let didWarnAboutUninitializedState;
let didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate;
Expand Down Expand Up @@ -836,7 +829,7 @@ function mountClassInstance(
const instance = workInProgress.stateNode;
instance.props = newProps;
instance.state = workInProgress.memoizedState;
instance.refs = emptyRefsObject;
instance.refs = {};

initializeUpdateQueue(workInProgress);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import type {Lanes} from './ReactFiberLane.old';
import type {UpdateQueue} from './ReactFiberClassUpdateQueue.old';
import type {Flags} from './ReactFiberFlags';

import * as React from 'react';
import {
LayoutStatic,
Update,
Expand Down Expand Up @@ -80,12 +79,6 @@ import {

const fakeInternalInstance = {};

// React.Component uses a shared frozen object by default.
// We'll use it to determine whether we need to initialize legacy refs.
export const emptyRefsObject: $FlowFixMe = React.Component
? new React.Component().refs
: {};

let didWarnAboutStateAssignmentForComponent;
let didWarnAboutUninitializedState;
let didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate;
Expand Down Expand Up @@ -836,7 +829,7 @@ function mountClassInstance(
const instance = workInProgress.stateNode;
instance.props = newProps;
instance.state = workInProgress.memoizedState;
instance.refs = emptyRefsObject;
instance.refs = {};

initializeUpdateQueue(workInProgress);

Expand Down

0 comments on commit 2976957

Please sign in to comment.