Skip to content

Commit 59ea017

Browse files
committed
fix(shared/hooks): 修复 useChildrenWithRefs 未能连通外部 ref 的问题
1 parent 58a8dd6 commit 59ea017

File tree

2 files changed

+37
-13
lines changed

2 files changed

+37
-13
lines changed

packages/shared/src/hooks/__tests__/useChildrenWithRefs.test.tsx

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
import { cloneElement, ReactNode, useEffect, useState, Children } from 'react';
1+
import {
2+
cloneElement,
3+
ReactNode,
4+
useEffect,
5+
useState,
6+
Children,
7+
useRef,
8+
} from 'react';
29
import { renderHook, render, act } from '@testing-library/react';
310
import { useChildrenWithRefs } from '@pkg/shared';
411

@@ -29,42 +36,58 @@ describe('useChildrenWithRefs', () => {
2936
expect(ref.mock.calls[0][0]).toBe(container.firstChild);
3037
});
3138
test('app', () => {
32-
const _refs: HTMLElement[] = [];
39+
const obj: { ref: HTMLElement | null; refs: HTMLElement[] } = {
40+
ref: null,
41+
refs: [],
42+
};
3343
const App = () => {
44+
const ref = useRef<HTMLDivElement>(null);
3445
const [children, setChildren] = useState<ReactNode>(
35-
<div className="foo">foo</div>,
46+
<div className="foo" ref={ref}>
47+
foo
48+
</div>,
3649
);
3750
const [newChildren, refs] = useChildrenWithRefs(children);
3851

3952
useEffect(() => {
40-
_refs.push(...refs);
53+
obj.refs = refs;
54+
obj.ref = ref.current;
4155
}, [refs]);
4256

4357
return (
4458
<>
4559
{newChildren}
46-
<button onClick={() => setChildren(<div className="bar">bar</div>)}>
60+
<button
61+
onClick={() =>
62+
setChildren(
63+
<div className="bar" ref={ref}>
64+
bar
65+
</div>,
66+
)
67+
}
68+
>
4769
切换 children
4870
</button>
4971
</>
5072
);
5173
};
5274

53-
expect(_refs).toEqual([]);
75+
expect(obj.refs).toEqual([]);
5476
const {
5577
container: { firstChild },
5678
} = render(<App />);
5779

5880
expect(firstChild).toHaveTextContent('foo');
5981
expect(firstChild).toHaveClass('foo');
60-
expect(_refs.length).toBe(1);
61-
expect(_refs[0]).toBe(firstChild);
82+
expect(obj.refs.length).toBe(1);
83+
expect(obj.refs[0]).toBe(firstChild);
84+
expect(obj.ref).toBe(firstChild);
6285

63-
_refs.length = 0;
6486
act(() => document.querySelector('button')!.click());
6587
expect(firstChild).toHaveTextContent('bar');
6688
expect(firstChild).toHaveClass('bar');
67-
expect(_refs.length).toBe(1);
68-
expect(_refs[0]).toBe(firstChild);
89+
expect(obj.refs.length).toBe(1);
90+
expect(obj.refs[0]).toBe(firstChild);
91+
expect(obj.ref).toBe(firstChild);
6992
});
7093
});

packages/shared/src/hooks/useChildrenWithRefs.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ export function useChildrenWithRefs(
2020
return cloneElement(child as ReactElement, {
2121
ref: (el: HTMLElement) => {
2222
refs[index] = el;
23-
const originRef = child.props.ref;
24-
23+
// ref 现在是直接放在 ReactElement 上的,props 虽然也有,但取的是 undefined
24+
const originRef = (child as any).ref;
25+
// const originRef = child.props.ref;
2526
if (!originRef) return;
2627
// 连通原来的 ref
2728
if (typeof originRef === 'function') originRef(el);

0 commit comments

Comments
 (0)