From f9ccaf23db7b770db52aa0c7c25750757ebb317b Mon Sep 17 00:00:00 2001 From: Joonas Sandell Date: Sun, 11 Jun 2023 22:38:53 +0300 Subject: [PATCH] Fix useInView with hook from the initial implementation. See desc. Copypaste and convert to js: https://github.com/cats-oss/use-intersection/blob/master/src/index.ts Original use-intersection react dependency hasn't been updated in a while: https://github.com/cats-oss/use-intersection/issues/143 Can't use the react-use version because it's not triggering sometimes: https://github.com/streamich/react-use/issues/2359 https://github.com/streamich/react-use/issues/2376 --- README.md | 1 - lib/useInView.js | 39 ++++++-------------- lib/useIntersection.js | 81 ++++++++++++++++++++++++++++++++++++++++++ package-lock.json | 11 ++++++ package.json | 1 + 5 files changed, 104 insertions(+), 29 deletions(-) create mode 100644 lib/useIntersection.js diff --git a/README.md b/README.md index 8380b108..9776990d 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,6 @@ Aside from this readme, there is additional information about the whole project ### Issues - Oras, last drop is not animated to the end. Possibly related to locomotive-scroll/react-locomotive-scroll updates. Noticed in production. -- Info: Not animating in, possible issue with useInView. Noticed in production. ### Notes diff --git a/lib/useInView.js b/lib/useInView.js index 3f5d18e4..fb83bdbb 100644 --- a/lib/useInView.js +++ b/lib/useInView.js @@ -1,46 +1,29 @@ -import { useEffect, useRef, useState } from 'react'; import { isString } from '@/lib/utility'; -import { useIntersection } from 'react-use'; +import { useIntersection } from '@/lib/useIntersection'; -/** - * https://github.com/streamich/react-use/issues/1664 - */ export const useInView = (ref, threshold = 0, once = true) => { if (isString(threshold)) threshold = parseFloat(threshold); if (threshold > 1) threshold = threshold.toFixed(2) * 0.01; const negativeValue = Math.sign(threshold) < 0; if (negativeValue) threshold = 0; - const mockRef = useRef(null); - const [intersectedOnce, setIntersectedOnce] = useState(false); - const intersection = useIntersection( - once && intersectedOnce ? mockRef : ref, - { - root: null, - rootMargin: '0px', - threshold, - }, - ); - const isIntersecting = intersection?.isIntersecting; - - useEffect(() => { - if (once && !intersectedOnce && isIntersecting) setIntersectedOnce(true); - }, [intersectedOnce, isIntersecting, once]); + const inView = useIntersection(ref, { + threshold, + once, + }); if (negativeValue) return true; - return once ? intersectedOnce : isIntersecting; + return inView; }; export const useInViewVideo = (ref, threshold = 0) => { const isVideo = ref.current && ref.current.tagName === 'VIDEO'; - const intersection = useIntersection(ref, { - root: null, - rootMargin: '0px', + + const inView = useIntersection(ref, { threshold, }); - const isIntersecting = intersection?.isIntersecting; - if (isVideo && isIntersecting) { + if (isVideo && inView) { const video = ref.current; video.muted = true; @@ -50,7 +33,7 @@ export const useInViewVideo = (ref, threshold = 0) => { } } - if (isVideo && !isIntersecting) { + if (isVideo && !inView) { const video = ref.current; if (!video.paused) { @@ -59,5 +42,5 @@ export const useInViewVideo = (ref, threshold = 0) => { } } - return intersection?.isIntersecting; + return inView; }; diff --git a/lib/useIntersection.js b/lib/useIntersection.js new file mode 100644 index 00000000..62a925b0 --- /dev/null +++ b/lib/useIntersection.js @@ -0,0 +1,81 @@ +import { useRef, useState, useEffect } from 'react'; +import shallowEqual from 'shallowequal'; + +/** + * Copypaste and conversion to js of the following: + * https://github.com/cats-oss/use-intersection/blob/master/src/index.ts + * + * Originals react dependency hasn't been updated in a while: + * https://github.com/cats-oss/use-intersection/issues/143 + * + * Can't use the react-use version because it's not triggering sometimes: + * https://github.com/streamich/react-use/issues/2359 + * https://github.com/streamich/react-use/issues/2376 + */ +export const useIntersection = (target, options = {}, callback) => { + const { defaultIntersecting, once, ...opts } = options; + const optsRef = useRef(opts); + const [intersecting, setIntersecting] = useState( + defaultIntersecting === true, + ); + const intersectedRef = useRef(false); + + useEffect(() => { + if (!shallowEqual(optsRef.current, opts)) { + optsRef.current = opts; + } + }); + + useEffect(() => { + if (target == null) { + return; + } + + const element = target instanceof Element ? target : target.current; + if (element == null) { + return; + } + + if (once && intersectedRef.current) { + return; + } + + const observer = new IntersectionObserver( + entries => { + const entry = entries[entries.length - 1]; + setIntersecting(entry.isIntersecting); + + if (callback != null) { + callback(entry); + } + + if (entry.isIntersecting) { + intersectedRef.current = true; + } + + if (once && entry.isIntersecting && element != null) { + observer.unobserve(element); + } + }, + { + ...optsRef.current, + root: + optsRef.current.root != null ? optsRef.current.root.current : null, + }, + ); + + observer.observe(element); + + return () => { + if (once && intersectedRef.current) { + return; + } + + if (element != null) { + observer.unobserve(element); + } + }; + }, [optsRef.current, target]); + + return intersecting; +}; diff --git a/package-lock.json b/package-lock.json index 5ec10879..6df4ac7d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "react-dom": "^17.0.2", "react-locomotive-scroll": "0.2.1", "react-use": "^17.4.0", + "shallowequal": "^1.1.0", "sharp": "^0.32.1", "smoothscroll-polyfill": "^0.4.4", "use-callback-ref": "^1.3.0" @@ -4581,6 +4582,11 @@ "node": ">=6.9" } }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, "node_modules/sharp": { "version": "0.32.1", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.1.tgz", @@ -8475,6 +8481,11 @@ "resolved": "https://registry.npmjs.org/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz", "integrity": "sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==" }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, "sharp": { "version": "0.32.1", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.1.tgz", diff --git a/package.json b/package.json index cd3705ae..c93dc83f 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "react-dom": "^17.0.2", "react-locomotive-scroll": "0.2.1", "react-use": "^17.4.0", + "shallowequal": "^1.1.0", "sharp": "^0.32.1", "smoothscroll-polyfill": "^0.4.4", "use-callback-ref": "^1.3.0"