Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix cloneElement using string ref w no owner #28797

Merged
merged 8 commits into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions packages/react/src/__tests__/ReactElementClone-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,22 @@ describe('ReactElementClone', () => {

const root = ReactDOMClient.createRoot(document.createElement('div'));
await act(() => root.render(<Grandparent />));
expect(component.childRef).toEqual({current: null});
expect(component.parentRef.current.xyzRef.current.tagName).toBe('SPAN');
if (gate(flags => flags.enableRefAsProp && flags.disableStringRefs)) {
expect(component.childRef).toEqual({current: null});
expect(component.parentRef.current.xyzRef.current.tagName).toBe('SPAN');
} else if (
gate(flags => !flags.enableRefAsProp && !flags.disableStringRefs)
) {
expect(component.childRef).toEqual({current: null});
expect(component.parentRef.current.xyzRef.current.tagName).toBe('SPAN');
} else if (
gate(flags => flags.enableRefAsProp && !flags.disableStringRefs)
) {
expect(component.childRef).toEqual({current: null});
expect(component.parentRef.current.xyzRef.current.tagName).toBe('SPAN');
Comment on lines +286 to +289
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm pretty sure this isn't running...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, not by default. thanks CI

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nah, it's getting hit, you have to run with the www variant:

yarn test-www --variant=true

Tested locally:

Screenshot 2024-04-09 at 3 01 39 PM

} else {
// Not going to bother testing every possible combination.
}
});

it('should overwrite props', async () => {
Expand Down Expand Up @@ -371,6 +385,15 @@ describe('ReactElementClone', () => {
) {
expect(clone.ref).toBe(element.ref);
expect(clone.props).toEqual({foo: 'ef'});
} else if (
gate(flags => flags.enableRefAsProp && !flags.disableStringRefs)
) {
expect(() => {
expect(clone.ref).toBe(element.ref);
}).toErrorDev('Accessing element.ref was removed in React 19', {
withoutStack: true,
});
expect(clone.props).toEqual({foo: 'ef', ref: element.ref});
Copy link
Member

@rickhanlonii rickhanlonii Apr 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@josephsavona since enableRefAsProp is on, the props will include the ref, so I updated the test.

} else {
// Not going to bother testing every possible combination.
}
Expand Down
2 changes: 1 addition & 1 deletion packages/react/src/jsx/ReactJSXElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -866,14 +866,14 @@ export function cloneElement(element, config, children) {

if (config != null) {
if (hasValidRef(config)) {
owner = ReactSharedInternals.owner;
if (!enableRefAsProp) {
// Silently steal the ref from the parent.
ref = config.ref;
if (!disableStringRefs) {
ref = coerceStringRef(ref, owner, element.type);
}
}
owner = ReactSharedInternals.owner;
}
if (hasValidKey(config)) {
if (__DEV__) {
Expand Down