diff --git a/src/image/index.tsx b/src/image/index.tsx index 80accd1c5..be60c9a31 100644 --- a/src/image/index.tsx +++ b/src/image/index.tsx @@ -1,4 +1,4 @@ -import React, { CSSProperties, useRef } from 'react'; +import React, { CSSProperties } from 'react'; import { Spin } from 'antd'; import useIntersectionObserver from '../useIntersectionObserver'; @@ -52,8 +52,7 @@ const ImageComponent = (props: IProps) => { const LazyImage = (props: IProps) => { const { src, ...rest } = props; - const imgRef = useRef(null); - useIntersectionObserver(([entry]) => { + const imgRef = useIntersectionObserver(([entry]) => { const { target, isIntersecting } = entry; if (isIntersecting) { const _target = target as HTMLImageElement; @@ -62,7 +61,7 @@ const LazyImage = (props: IProps) => { _target.style.opacity = '1'; }; } - }, imgRef); + }); return ; }; diff --git a/src/useIntersectionObserver/__tests__/useIntersectionObserver.test.ts b/src/useIntersectionObserver/__tests__/useIntersectionObserver.test.ts index 0460bb125..41db88180 100644 --- a/src/useIntersectionObserver/__tests__/useIntersectionObserver.test.ts +++ b/src/useIntersectionObserver/__tests__/useIntersectionObserver.test.ts @@ -1,4 +1,3 @@ -import { RefObject } from 'react'; import { act, renderHook } from '@testing-library/react-hooks'; import useIntersectionObserver from '../index'; @@ -31,25 +30,35 @@ describe('useIntersectionObserver', () => { }); it('should observe target element and disconnect on unmount', () => { - const ref = { current: document.createElement('div') }; const callback = jest.fn(); const options = { threshold: 0, root: null, rootMargin: '0%' }; - const { unmount } = renderHook(() => useIntersectionObserver(callback, ref, options)); + + const divElement = document.createElement('div'); + document.body.appendChild(divElement); + + const { unmount } = renderHook(() => { + const ref = useIntersectionObserver(callback, options); + ref.current = divElement; + return ref; + }); expect(window.IntersectionObserver).toHaveBeenCalledWith(expect.any(Function), options); - expect(observeMock).toHaveBeenCalledWith(ref.current); + expect(observeMock).toHaveBeenCalledWith(divElement); act(() => { unmount(); }); expect(disconnectMock).toHaveBeenCalled(); }); - it('should not observe target element if not provided', () => { + it('should not observe target element if ref is null', () => { const callback = jest.fn(); const options = { threshold: 0, root: null, rootMargin: '0%' }; - const { unmount } = renderHook(() => - useIntersectionObserver(callback, null as unknown as RefObject, options) - ); - expect(window.IntersectionObserver).toHaveBeenCalledWith(expect.any(Function), options); + + const { unmount } = renderHook(() => { + const ref = useIntersectionObserver(callback, options); + ref.current = null; + return ref; + }); + expect(observeMock).not.toHaveBeenCalled(); act(() => { unmount(); diff --git a/src/useIntersectionObserver/demos/basic.tsx b/src/useIntersectionObserver/demos/basic.tsx index a11e5b528..bb149bd73 100644 --- a/src/useIntersectionObserver/demos/basic.tsx +++ b/src/useIntersectionObserver/demos/basic.tsx @@ -1,20 +1,18 @@ -import React, { useRef } from 'react'; +import React from 'react'; import useIntersectionObserver from '..'; const Basic = () => { - const divRef = useRef(null); - const handleObserverCb = ([entry]: IntersectionObserverEntry[]) => { if (entry.isIntersecting) alert('hi, 我展示了'); }; - useIntersectionObserver(handleObserverCb, divRef); + const ref = useIntersectionObserver(handleObserverCb); return (
占位,往下滑动
-
+
展示了
diff --git a/src/useIntersectionObserver/demos/imgLazy.tsx b/src/useIntersectionObserver/demos/imgLazy.tsx index 446f1fdd4..fe5d1cb74 100644 --- a/src/useIntersectionObserver/demos/imgLazy.tsx +++ b/src/useIntersectionObserver/demos/imgLazy.tsx @@ -1,10 +1,8 @@ -import React, { useRef } from 'react'; +import React from 'react'; import useIntersectionObserver from '..'; const Basic = () => { - const imgRef = useRef(null); - const handleObserverCb = ([entry]: IntersectionObserverEntry[]) => { const { target, isIntersecting } = entry; if (isIntersecting) { @@ -16,7 +14,7 @@ const Basic = () => { } }; - useIntersectionObserver(handleObserverCb, imgRef, {}); + const imgRef = useIntersectionObserver(handleObserverCb); return (
diff --git a/src/useIntersectionObserver/index.ts b/src/useIntersectionObserver/index.ts index 1438e5ac0..640338223 100644 --- a/src/useIntersectionObserver/index.ts +++ b/src/useIntersectionObserver/index.ts @@ -1,10 +1,11 @@ -import { RefObject, useEffect, useState } from 'react'; +import { MutableRefObject, useEffect, useRef, useState } from 'react'; -const useIntersectionObserver = ( +const useIntersectionObserver = ( callback: IntersectionObserverCallback, - target: RefObject, options: IntersectionObserverInit & { freezeOnceVisible?: boolean } = {} ) => { + const ref = useRef(null); + const { threshold = 0, root = null, rootMargin = '0%', freezeOnceVisible = false } = options; const [entry, setEntry] = useState(); const frozen = entry?.isIntersecting && freezeOnceVisible; @@ -18,17 +19,17 @@ const useIntersectionObserver = ( }; useEffect(() => { - const node = target?.current; // DOM Ref + const node = ref.current; const hasIOSupport = !!window.IntersectionObserver; if (frozen || !node) return; if (!hasIOSupport) { // 如果不支持 IntersectionObserver 执行一个默认行为 const callbackEntry = { - boundingClientRect: node?.getBoundingClientRect() ?? null, - intersectionRatio: node ? 1 : 0, - intersectionRect: node?.getBoundingClientRect() ?? null, - isIntersecting: !!node, + boundingClientRect: node.getBoundingClientRect() ?? null, + intersectionRatio: 1, + intersectionRect: node.getBoundingClientRect() ?? null, + isIntersecting: true, rootBounds: null, target: node, time: Date.now(), @@ -40,7 +41,9 @@ const useIntersectionObserver = ( observer.observe(node); return () => observer.disconnect(); - }, [target?.current, JSON.stringify(threshold), root, rootMargin, frozen]); + }, [JSON.stringify(threshold), root, rootMargin, frozen]); + + return ref as MutableRefObject; }; export default useIntersectionObserver;