Skip to content

Commit 9e42e95

Browse files
committed
fix: fix for #82
1 parent 04c8327 commit 9e42e95

File tree

2 files changed

+37
-8
lines changed

2 files changed

+37
-8
lines changed

src/Hyperlink.tsx

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ class Hyperlink extends Component<HyperlinkProps, HyperlinkState> {
3232
}
3333

3434
render() {
35-
const { ...viewProps } = this.props;
35+
// Avoid spreading React special props such as `key` or `ref`
36+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
37+
const { key: _key, ref: _ref, ...viewProps } = this.props as any;
3638

3739
// If no link handlers or styles, just render children as-is
3840
if (
@@ -96,6 +98,8 @@ class Hyperlink extends Component<HyperlinkProps, HyperlinkState> {
9698

9799
// Create component props (ref and key are React-specific and not in TextProps)
98100
const componentProps = component.props as TextProps;
101+
delete (componentProps as { ref?: unknown }).ref;
102+
delete (componentProps as { key?: unknown }).key;
99103

100104
try {
101105
this.state.linkifyIt
@@ -157,11 +161,9 @@ class Hyperlink extends Component<HyperlinkProps, HyperlinkState> {
157161
let { props: { children } = { children: undefined } } = component || {};
158162
if (!children) return component;
159163

160-
const componentProps = {
161-
...component.props,
162-
ref: undefined,
163-
key: undefined,
164-
};
164+
const componentProps = component.props as TextProps;
165+
delete (componentProps as { ref?: unknown }).ref;
166+
delete (componentProps as { key?: unknown }).key;
165167

166168
return React.cloneElement(
167169
component,
@@ -214,13 +216,17 @@ export default class extends Component<HyperlinkProps> {
214216

215217
render() {
216218
const onPress = this.props.onPress ?? this.handleLink;
219+
// Do not forward `key`/`ref` to the inner `Hyperlink` to avoid
220+
// React warning about spreading a props object that contains `key`.
221+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
222+
const { key: _key, ref: _ref, ...rest } = this.props as any;
217223
return this.props.linkDefault ? (
218224
<Hyperlink
219-
{...this.props}
225+
{...rest}
220226
onPress={onPress}
221227
/>
222228
) : (
223-
<Hyperlink {...this.props} />
229+
<Hyperlink {...rest} />
224230
);
225231
}
226232
}

src/__tests__/index.test.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,4 +661,27 @@ describe('Hyperlink', () => {
661661
testSpy.mockRestore();
662662
});
663663
});
664+
665+
it('does not warn when passing `key` prop to outer component', () => {
666+
const consoleError = jest
667+
.spyOn(console, 'error')
668+
.mockImplementation(() => {});
669+
// Render with a key passed to the outer Hyperlink component
670+
render(
671+
<View key='outer-key'>
672+
<Hyperlink linkDefault>
673+
<Text>Visit http://example.com</Text>
674+
</Hyperlink>
675+
,
676+
</View>,
677+
);
678+
679+
const calls = (consoleError.mock.calls || []).map(c => String(c[0] || ''));
680+
const found = calls.some(msg =>
681+
/props object containing a "key" prop is being spread into JSX/.test(msg),
682+
);
683+
expect(found).toBe(false);
684+
685+
consoleError.mockRestore();
686+
});
664687
});

0 commit comments

Comments
 (0)