From 9bb7047b7395aaba3da096697ef30aa46d188ec5 Mon Sep 17 00:00:00 2001 From: streamich Date: Sun, 24 Mar 2019 17:43:35 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20keep=20global=20state=20?= =?UTF-8?q?of=20all=20useLockBodyScroll=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change will keep document body locked as long as at least one hook is enabled on the page. Maybe it makes sense to generalize this logic for other side-effect hooks. One such hook could be useBlurBody that blurs page - useful for modals and overlays. --- src/__stories__/useLockBodyScroll.story.tsx | 22 +++++++++--- src/useLockBodyScroll.ts | 37 +++++++++++++-------- 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/src/__stories__/useLockBodyScroll.story.tsx b/src/__stories__/useLockBodyScroll.story.tsx index 2c14ff5e83..b701d27d77 100644 --- a/src/__stories__/useLockBodyScroll.story.tsx +++ b/src/__stories__/useLockBodyScroll.story.tsx @@ -5,20 +5,34 @@ import ShowDocs from '../util/ShowDocs'; const Demo = () => { const [locked, toggleLocked] = useToggle(false) - useLockBodyScroll(locked); return (
-
); }; +const AnotherComponent = () => { + const [locked, toggleLocked] = useToggle(false) + useLockBodyScroll(locked); + + return ( + + ); +}; + storiesOf('Side effects|useLockBodyScroll', module) .add('Docs', () => ) - .add('Demo', () => - + .add('Demo', () => ) + .add('Two hooks on page', () => + <> + + + ) diff --git a/src/useLockBodyScroll.ts b/src/useLockBodyScroll.ts index d0d2023198..67b2220659 100644 --- a/src/useLockBodyScroll.ts +++ b/src/useLockBodyScroll.ts @@ -1,19 +1,30 @@ -import {useRef, useEffect} from 'react'; -import {isClient} from './util'; -import useUnmount from './useUnmount'; +import {useEffect} from 'react'; -const useLockBodyScroll = (enabled: boolean = true) => { - const originalOverflow = useRef( - isClient ? window.getComputedStyle(document.body).overflow : 'visible' - ); +let counter = 0; +let originalOverflow: string | null = null; + +const lock = () => { + originalOverflow = window.getComputedStyle(document.body).overflow; + document.body.style.overflow = 'hidden'; +}; + +const unlock = () => { + document.body.style.overflow = originalOverflow; + originalOverflow = null; +}; - useEffect(() => { - document.body.style.overflow = enabled ? "hidden" : originalOverflow.current; - }, [enabled]); +const increment = () => { + counter++; + if (counter === 1) lock(); +}; - useUnmount(() => { - document.body.style.overflow = originalOverflow.current - }); +const decrement = () => { + counter--; + if (counter === 0) unlock(); +}; + +const useLockBodyScroll = (enabled: boolean = true) => { + useEffect(() => enabled ? (increment(), decrement) : undefined, [enabled]); } export default useLockBodyScroll;