From c72d1107e4ac738198998d781327d7d244c8850d Mon Sep 17 00:00:00 2001 From: LuckyFBB <976060700@qq.com> Date: Fri, 8 Nov 2024 14:39:44 +0800 Subject: [PATCH 1/2] fix(useintersectionobserver): remove ref from props and createRef in useIntersectionObserver --- src/image/index.tsx | 7 +++-- .../__tests__/useIntersectionObserver.test.ts | 27 ++++++++++++------- src/useIntersectionObserver/demos/basic.tsx | 8 +++--- src/useIntersectionObserver/demos/imgLazy.tsx | 6 ++--- src/useIntersectionObserver/index.ts | 21 ++++++++------- 5 files changed, 38 insertions(+), 31 deletions(-) diff --git a/src/image/index.tsx b/src/image/index.tsx index 80accd1c5..4ad1ffa37 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..476d51917 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..1bfd7c3a7 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..e2a7556e9 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..b59eddf03 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; From eb77f7f3a8d3a892ecd31e0ab4a23fda26de5ed6 Mon Sep 17 00:00:00 2001 From: LuckyFBB <976060700@qq.com> Date: Mon, 2 Dec 2024 10:02:57 +0800 Subject: [PATCH 2/2] fix(useintersectionobserver): change return, use variable --- src/image/index.tsx | 2 +- .../__tests__/useIntersectionObserver.test.ts | 4 ++-- src/useIntersectionObserver/demos/basic.tsx | 2 +- src/useIntersectionObserver/demos/imgLazy.tsx | 2 +- src/useIntersectionObserver/index.ts | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/image/index.tsx b/src/image/index.tsx index 4ad1ffa37..be60c9a31 100644 --- a/src/image/index.tsx +++ b/src/image/index.tsx @@ -52,7 +52,7 @@ const ImageComponent = (props: IProps) => { const LazyImage = (props: IProps) => { const { src, ...rest } = props; - const [imgRef] = useIntersectionObserver(([entry]) => { + const imgRef = useIntersectionObserver(([entry]) => { const { target, isIntersecting } = entry; if (isIntersecting) { const _target = target as HTMLImageElement; diff --git a/src/useIntersectionObserver/__tests__/useIntersectionObserver.test.ts b/src/useIntersectionObserver/__tests__/useIntersectionObserver.test.ts index 476d51917..41db88180 100644 --- a/src/useIntersectionObserver/__tests__/useIntersectionObserver.test.ts +++ b/src/useIntersectionObserver/__tests__/useIntersectionObserver.test.ts @@ -37,7 +37,7 @@ describe('useIntersectionObserver', () => { document.body.appendChild(divElement); const { unmount } = renderHook(() => { - const [ref] = useIntersectionObserver(callback, options); + const ref = useIntersectionObserver(callback, options); ref.current = divElement; return ref; }); @@ -54,7 +54,7 @@ describe('useIntersectionObserver', () => { const options = { threshold: 0, root: null, rootMargin: '0%' }; const { unmount } = renderHook(() => { - const [ref] = useIntersectionObserver(callback, options); + const ref = useIntersectionObserver(callback, options); ref.current = null; return ref; }); diff --git a/src/useIntersectionObserver/demos/basic.tsx b/src/useIntersectionObserver/demos/basic.tsx index 1bfd7c3a7..bb149bd73 100644 --- a/src/useIntersectionObserver/demos/basic.tsx +++ b/src/useIntersectionObserver/demos/basic.tsx @@ -7,7 +7,7 @@ const Basic = () => { if (entry.isIntersecting) alert('hi, 我展示了'); }; - const [ref] = useIntersectionObserver(handleObserverCb); + const ref = useIntersectionObserver(handleObserverCb); return (
diff --git a/src/useIntersectionObserver/demos/imgLazy.tsx b/src/useIntersectionObserver/demos/imgLazy.tsx index e2a7556e9..fe5d1cb74 100644 --- a/src/useIntersectionObserver/demos/imgLazy.tsx +++ b/src/useIntersectionObserver/demos/imgLazy.tsx @@ -14,7 +14,7 @@ const Basic = () => { } }; - const [imgRef] = useIntersectionObserver(handleObserverCb); + const imgRef = useIntersectionObserver(handleObserverCb); return (
diff --git a/src/useIntersectionObserver/index.ts b/src/useIntersectionObserver/index.ts index b59eddf03..640338223 100644 --- a/src/useIntersectionObserver/index.ts +++ b/src/useIntersectionObserver/index.ts @@ -43,7 +43,7 @@ const useIntersectionObserver = ( return () => observer.disconnect(); }, [JSON.stringify(threshold), root, rootMargin, frozen]); - return [ref as MutableRefObject]; + return ref as MutableRefObject; }; export default useIntersectionObserver;