diff --git a/packages/react-reconciler/src/ReactFiberClassComponent.js b/packages/react-reconciler/src/ReactFiberClassComponent.js
index ac1b7fb3ab8e7..6bf04da4b41b6 100644
--- a/packages/react-reconciler/src/ReactFiberClassComponent.js
+++ b/packages/react-reconciler/src/ReactFiberClassComponent.js
@@ -819,6 +819,7 @@ function mountClassInstance(
const instance = workInProgress.stateNode;
instance.props = newProps;
instance.state = workInProgress.memoizedState;
+ instance.refs = {};
initializeUpdateQueue(workInProgress);
diff --git a/packages/react-reconciler/src/__tests__/ReactFiberRefs-test.js b/packages/react-reconciler/src/__tests__/ReactFiberRefs-test.js
index 175c849d94710..e46387d8cc7dd 100644
--- a/packages/react-reconciler/src/__tests__/ReactFiberRefs-test.js
+++ b/packages/react-reconciler/src/__tests__/ReactFiberRefs-test.js
@@ -138,28 +138,4 @@ describe('ReactFiberRefs', () => {
);
expect(refProp).toBe('child');
});
-
- test('strings refs can be codemodded to callback refs', async () => {
- let app;
- class App extends React.Component {
- render() {
- app = this;
- return (
-
{
- // `refs` used to be a shared frozen object unless/until a string
- // ref attached by the reconciler, but it's not anymore so that we
- // can codemod string refs to userspace callback refs.
- this.refs.div = el;
- }}
- />
- );
- }
- }
-
- const root = ReactNoop.createRoot();
- await act(() => root.render(
));
- expect(app.refs.div.prop).toBe('Hello!');
- });
});
diff --git a/packages/react/src/ReactBaseClasses.js b/packages/react/src/ReactBaseClasses.js
index ce81071937574..7895a97e3a1ef 100644
--- a/packages/react/src/ReactBaseClasses.js
+++ b/packages/react/src/ReactBaseClasses.js
@@ -8,13 +8,19 @@
import ReactNoopUpdateQueue from './ReactNoopUpdateQueue';
import assign from 'shared/assign';
+const emptyObject = {};
+if (__DEV__) {
+ Object.freeze(emptyObject);
+}
+
/**
* Base class helpers for the updating state of a component.
*/
function Component(props, context, updater) {
this.props = props;
this.context = context;
- this.refs = {};
+ // If a component has string refs, we will assign a different object later.
+ this.refs = emptyObject;
// We initialize the default updater but the real one gets injected by the
// renderer.
this.updater = updater || ReactNoopUpdateQueue;
@@ -127,7 +133,7 @@ function PureComponent(props, context, updater) {
this.props = props;
this.context = context;
// If a component has string refs, we will assign a different object later.
- this.refs = {};
+ this.refs = emptyObject;
this.updater = updater || ReactNoopUpdateQueue;
}