From 9014a9e393522cc12a809b4170821be5ccdf34d4 Mon Sep 17 00:00:00 2001 From: Josep M Sobrepere Date: Sat, 17 Aug 2019 23:57:57 +0200 Subject: [PATCH] Improve useNearScreen implementation --- strategies/useNearScreen.js | 56 +++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/strategies/useNearScreen.js b/strategies/useNearScreen.js index 70ad66c..3115ce2 100644 --- a/strategies/useNearScreen.js +++ b/strategies/useNearScreen.js @@ -1,27 +1,47 @@ import {useState, useEffect} from 'react' +const targetCallbacks = new WeakMap() +const observerP = + typeof window !== 'undefined' && + Promise.resolve( + typeof window.IntersectionObserver === 'undefined' && + import('intersection-observer') + ).then( + () => + new window.IntersectionObserver(entries => { + entries + .filter(e => e.isIntersecting) + .map(e => targetCallbacks.get(e.target)) + .filter(Boolean) + .forEach(cb => cb()) + }) + ) + +function whenIntersecting(target, cb) { + function unsubscribe() { + observerP.then(observer => { + observer.unobserve(target) + targetCallbacks.delete(target) + }) + } + + observerP.then(observer => { + observer.observe(target) + targetCallbacks.set(target, () => { + unsubscribe() + cb() + }) + }) + + return unsubscribe +} + export const useNearScreen = ({ref}) => { const [show, setShow] = useState(false) useEffect( - function() { - if (!ref || !ref.current) return - - Promise.resolve( - typeof window.IntersectionObserver !== 'undefined' - ? window.IntersectionObserver - : import('intersection-observer') - ).then(() => { - const observer = new window.IntersectionObserver(function(entries) { - const {isIntersecting} = entries[0] - if (isIntersecting) { - setShow(true) - observer.disconnect() - } - }) - observer.observe(ref.current) - }) - }, + () => + ref && ref.current && whenIntersecting(ref.current, () => setShow(true)), [ref] )