Skip to content

Commit

Permalink
feat: support ref track of dom node (#172)
Browse files Browse the repository at this point in the history
* chore: support ref

* test: add test case

* Update src/SingleObserver/index.tsx

Co-authored-by: kiner-tang(文辉) <1127031143@qq.com>

* Update src/index.tsx

Co-authored-by: kiner-tang(文辉) <1127031143@qq.com>

---------

Co-authored-by: kiner-tang(文辉) <1127031143@qq.com>
  • Loading branch information
zombieJ and kiner-tang authored Feb 3, 2023
1 parent 3cb0e05 commit e29ad57
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 7 deletions.
18 changes: 15 additions & 3 deletions src/SingleObserver/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export interface SingleObserverProps extends ResizeObserverProps {
children: React.ReactElement | ((ref: React.RefObject<Element>) => React.ReactElement);
}

export default function SingleObserver(props: SingleObserverProps) {
function SingleObserver(props: SingleObserverProps, ref: React.Ref<HTMLElement>) {
const { children, disabled } = props;
const elementRef = React.useRef<Element>(null);
const wrapperRef = React.useRef<DomWrapper>(null);
Expand Down Expand Up @@ -39,6 +39,11 @@ export default function SingleObserver(props: SingleObserverProps) {
[originRef, elementRef],
);

const getDom = () =>
findDOMNode<HTMLElement>(elementRef.current) || findDOMNode<HTMLElement>(wrapperRef.current);

React.useImperativeHandle(ref, () => getDom());

// =========================== Observe ============================
const propsRef = React.useRef<SingleObserverProps>(props);
propsRef.current = props;
Expand Down Expand Up @@ -91,8 +96,7 @@ export default function SingleObserver(props: SingleObserverProps) {

// Dynamic observe
React.useEffect(() => {
const currentElement: HTMLElement =
findDOMNode(elementRef.current) || findDOMNode(wrapperRef.current);
const currentElement: HTMLElement = getDom();

if (currentElement && !disabled) {
observe(currentElement, onInternalResize);
Expand All @@ -112,3 +116,11 @@ export default function SingleObserver(props: SingleObserverProps) {
</DomWrapper>
);
}

const RefSingleObserver = React.forwardRef(SingleObserver);

if (process.env.NODE_ENV !== 'production') {
RefSingleObserver.displayName = 'SingleObserver';
}

export default RefSingleObserver;
18 changes: 14 additions & 4 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export interface ResizeObserverProps {
onResize?: OnResize;
}

function ResizeObserver(props: ResizeObserverProps) {
function ResizeObserver(props: ResizeObserverProps, ref: React.Ref<HTMLElement>) {
const { children } = props;
const childNodes = typeof children === 'function' ? [children] : toArray(children);

Expand All @@ -42,13 +42,23 @@ function ResizeObserver(props: ResizeObserverProps) {
return childNodes.map((child, index) => {
const key = child?.key || `${INTERNAL_PREFIX_KEY}-${index}`;
return (
<SingleObserver {...props} key={key}>
<SingleObserver {...props} key={key} ref={index === 0 ? ref : undefined}>
{child}
</SingleObserver>
);
}) as any as React.ReactElement;
}

ResizeObserver.Collection = Collection;
const RefResizeObserver = React.forwardRef(ResizeObserver) as React.ForwardRefExoticComponent<
React.PropsWithoutRef<ResizeObserverProps> & React.RefAttributes<any>
> & {
Collection: typeof Collection;
};

export default ResizeObserver;
if (process.env.NODE_ENV !== 'production') {
RefResizeObserver.displayName = 'ResizeObserver';
}

RefResizeObserver.Collection = Collection;

export default RefResizeObserver;
13 changes: 13 additions & 0 deletions tests/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -245,4 +245,17 @@ describe('ResizeObserver', () => {

expect(wrapper.exists('.block')).toBeTruthy();
});

it('ref-able', () => {
const domRef = React.createRef();

const wrapper = mount(
<ResizeObserver ref={domRef}>
<div className="block" />
</ResizeObserver>,
);

expect(domRef.current instanceof HTMLDivElement).toBeTruthy();
expect(domRef.current).toBe(wrapper.find('div.block').getDOMNode());
});
});

0 comments on commit e29ad57

Please sign in to comment.