Skip to content

Commit b039be6

Browse files
authoredApr 24, 2024··
Unrevert "Support writing to this.refs from userspace" (#28879)
Reverts #28877 We found the cause of the regression and should be able to land this again.
1 parent 6f6e375 commit b039be6

File tree

3 files changed

+35
-11
lines changed

3 files changed

+35
-11
lines changed
 

‎packages/react-reconciler/src/ReactFiberClassComponent.js

+9-3
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ import {
1919
} from './ReactFiberFlags';
2020
import {
2121
debugRenderPhaseSideEffectsForStrictMode,
22+
disableDefaultPropsExceptForClasses,
2223
disableLegacyContext,
24+
disableStringRefs,
2325
enableDebugTracing,
24-
enableSchedulingProfiler,
2526
enableLazyContextPropagation,
2627
enableRefAsProp,
27-
disableDefaultPropsExceptForClasses,
28+
enableSchedulingProfiler,
2829
} from 'shared/ReactFeatureFlags';
2930
import ReactStrictModeWarnings from './ReactStrictModeWarnings';
3031
import {isMounted} from './ReactFiberTreeReflection';
@@ -819,7 +820,12 @@ function mountClassInstance(
819820
const instance = workInProgress.stateNode;
820821
instance.props = newProps;
821822
instance.state = workInProgress.memoizedState;
822-
instance.refs = {};
823+
if (!disableStringRefs) {
824+
// When string refs are used in create-react-class legacy components,
825+
// we need to make refs writable unless we patch all such copies of the
826+
// class code that sets to a frozen emptyObject.
827+
instance.refs = {};
828+
}
823829

824830
initializeUpdateQueue(workInProgress);
825831

‎packages/react-reconciler/src/__tests__/ReactFiberRefs-test.js

+24
Original file line numberDiff line numberDiff line change
@@ -138,4 +138,28 @@ describe('ReactFiberRefs', () => {
138138
);
139139
expect(refProp).toBe('child');
140140
});
141+
142+
test('strings refs can be codemodded to callback refs', async () => {
143+
let app;
144+
class App extends React.Component {
145+
render() {
146+
app = this;
147+
return (
148+
<div
149+
prop="Hello!"
150+
ref={el => {
151+
// `refs` used to be a shared frozen object unless/until a string
152+
// ref attached by the reconciler, but it's not anymore so that we
153+
// can codemod string refs to userspace callback refs.
154+
this.refs.div = el;
155+
}}
156+
/>
157+
);
158+
}
159+
}
160+
161+
const root = ReactNoop.createRoot();
162+
await act(() => root.render(<App />));
163+
expect(app.refs.div.prop).toBe('Hello!');
164+
});
141165
});

‎packages/react/src/ReactBaseClasses.js

+2-8
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,13 @@
88
import ReactNoopUpdateQueue from './ReactNoopUpdateQueue';
99
import assign from 'shared/assign';
1010

11-
const emptyObject = {};
12-
if (__DEV__) {
13-
Object.freeze(emptyObject);
14-
}
15-
1611
/**
1712
* Base class helpers for the updating state of a component.
1813
*/
1914
function Component(props, context, updater) {
2015
this.props = props;
2116
this.context = context;
22-
// If a component has string refs, we will assign a different object later.
23-
this.refs = emptyObject;
17+
this.refs = {};
2418
// We initialize the default updater but the real one gets injected by the
2519
// renderer.
2620
this.updater = updater || ReactNoopUpdateQueue;
@@ -133,7 +127,7 @@ function PureComponent(props, context, updater) {
133127
this.props = props;
134128
this.context = context;
135129
// If a component has string refs, we will assign a different object later.
136-
this.refs = emptyObject;
130+
this.refs = {};
137131
this.updater = updater || ReactNoopUpdateQueue;
138132
}
139133

0 commit comments

Comments
 (0)
Please sign in to comment.