Skip to content

Commit e41501d

Browse files
authored
Fix refs on links and merge props (#4360)
1 parent e083a93 commit e41501d

File tree

4 files changed

+16
-7
lines changed

4 files changed

+16
-7
lines changed

packages/@react-spectrum/link/src/Link.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
import {classNames, getWrappedElement, useSlotProps, useStyleProps} from '@react-spectrum/utils';
1414
import {FocusRing} from '@react-aria/focus';
15-
import {mergeProps} from '@react-aria/utils';
15+
import {mergeProps, mergeRefs} from '@react-aria/utils';
1616
import React, {useRef} from 'react';
1717
import {SpectrumLinkProps} from '@react-types/link';
1818
import styles from '@adobe/spectrum-css-temp/components/link/vars.css';
@@ -47,14 +47,17 @@ export function Link(props: SpectrumLinkProps) {
4747
elementType: typeof children === 'string' ? 'span' : 'a'
4848
}, ref);
4949

50+
let wrappedChild = getWrappedElement(children);
51+
5052
return (
5153
<FocusRing focusRingClass={classNames(styles, 'focus-ring')}>
5254
{React.cloneElement(
53-
getWrappedElement(children),
55+
wrappedChild,
5456
{
5557
...styleProps,
56-
...mergeProps(linkProps, hoverProps),
57-
ref,
58+
...mergeProps(wrappedChild.props, linkProps, hoverProps),
59+
// @ts-ignore https://github.com/facebook/react/issues/8873
60+
ref: wrappedChild.ref ? mergeRefs(ref, wrappedChild.ref) : ref,
5861
className: classNames(
5962
styles,
6063
'spectrum-Link',

packages/@react-spectrum/link/stories/Link.stories.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ export let WithChildren: LinkStory = {
7474
name: 'children: a'
7575
};
7676

77+
export let BlockNavigation: LinkStory = {
78+
args: {children: <a href="//example.com" target="_self" onClick={(e) => e.preventDefault()}>This is a React Spectrum Link</a>}
79+
};
80+
7781
export let OnClick: LinkStory = {
7882
...Default,
7983
args: {...Default.args},

packages/@react-spectrum/link/test/Link.test.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,16 @@ describe('Link', function () {
7373
});
7474

7575
it('Wraps custom child element', () => {
76+
let ref = React.createRef();
7677
let {getByRole} = render(
7778
<Link UNSAFE_className="test-class" onPress={onPressSpy} >
78-
<a href="#only-hash-in-jsdom" >Click me </a>
79+
<a href="#only-hash-in-jsdom" ref={ref}>Click me </a>
7980
</Link>
8081
);
8182
let link = getByRole('link');
8283
expect(link).toBeDefined();
8384
expect(link.nodeName).toBe('A');
85+
expect(ref.current).toBe(link);
8486
expect(link).toHaveAttribute('class', expect.stringContaining('test-class'));
8587
expect(link).toHaveAttribute('href', '#only-hash-in-jsdom');
8688
triggerPress(link);

packages/@react-spectrum/utils/src/getWrappedElement.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
* governing permissions and limitations under the License.
1111
*/
1212

13-
import React, {ReactElement, ReactNode} from 'react';
13+
import React, {JSXElementConstructor, ReactElement, ReactNode} from 'react';
1414

15-
export function getWrappedElement(children: string | ReactElement | ReactNode): ReactElement {
15+
export function getWrappedElement(children: string | ReactElement | ReactNode): ReactElement<any, JSXElementConstructor<any>> {
1616
let element;
1717
if (typeof children === 'string') {
1818
element = <span>{children}</span>;

0 commit comments

Comments
 (0)