-
Notifications
You must be signed in to change notification settings - Fork 47.4k
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
Changes from 4 commits
9d2dd81
f7b42b3
c97b811
b7f5119
28d13d2
bb30f2b
9aedf71
5162111
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -274,8 +274,55 @@ 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'); | ||||||
} else { | ||||||
// Not going to bother testing every possible combination. | ||||||
} | ||||||
}); | ||||||
|
||||||
it('should steal the ref if a new string ref is specified', async () => { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dupe test name
Suggested change
|
||||||
if (gate(flags => !flags.enableRefAsProp && !flags.disableStringRefs)) { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of inlining this, you can add this above the test:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nope, even fixing this to remove the "flags." from each flag, it causes failures in all the other flag combinations, which expect the test to fail |
||||||
await expect(async () => { | ||||||
// create an element without an owner | ||||||
const element = React.createElement('div', {id: 'some-id'}); | ||||||
class Parent extends React.Component { | ||||||
render() { | ||||||
return <Child>{element}</Child>; | ||||||
} | ||||||
} | ||||||
let child; | ||||||
class Child extends React.Component { | ||||||
render() { | ||||||
child = this; | ||||||
const clone = React.cloneElement(this.props.children, { | ||||||
ref: 'xyz', | ||||||
}); | ||||||
return <div>{clone}</div>; | ||||||
} | ||||||
} | ||||||
|
||||||
const root = ReactDOMClient.createRoot(document.createElement('div')); | ||||||
await act(() => root.render(<Parent />)); | ||||||
expect(child.refs.xyz.tagName).toBe('DIV'); | ||||||
}).toErrorDev([ | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. before the fix this failed, hitting the case where there was no owner during string ref conversion |
||||||
'Warning: Component "Child" contains the string ref "xyz". Support for ' + | ||||||
'string refs will be removed in a future major release. We recommend ' + | ||||||
'using useRef() or createRef() instead. Learn more about using refs ' + | ||||||
'safely here: https://react.dev/link/strict-mode-string-ref', | ||||||
]); | ||||||
} | ||||||
}); | ||||||
|
||||||
it('should overwrite props', async () => { | ||||||
|
@@ -371,6 +418,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}); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @josephsavona since |
||||||
} else { | ||||||
// Not going to bother testing every possible combination. | ||||||
} | ||||||
|
There was a problem hiding this comment.
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...
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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:
Tested locally: