Skip to content

Commit

Permalink
feat: 🎸 keep global state of all useLockBodyScroll hooks
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
streamich committed Mar 26, 2019
1 parent 30ee224 commit 5dd10e9
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 17 deletions.
22 changes: 18 additions & 4 deletions src/__stories__/useLockBodyScroll.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,34 @@ import ShowDocs from '../util/ShowDocs';

const Demo = () => {
const [locked, toggleLocked] = useToggle(false)

useLockBodyScroll(locked);

return (
<div style={{height: '200vh'}}>
<button onClick={() => toggleLocked()} style={{position: 'fixed', left: 0, right: 0}}>
<button onClick={() => toggleLocked()} style={{position: 'fixed', left: 0}}>
{locked ? 'Unlock' : 'Lock'}
</button>
</div>
);
};

const AnotherComponent = () => {
const [locked, toggleLocked] = useToggle(false)
useLockBodyScroll(locked);

return (
<button onClick={() => toggleLocked()} style={{position: 'fixed', left: 0, top: 40}}>
{locked ? 'Unlock' : 'Lock'}
</button>
);
};

storiesOf('Side effects|useLockBodyScroll', module)
.add('Docs', () => <ShowDocs md={require('../../docs/useLockBodyScroll.md')} />)
.add('Demo', () =>
<Demo/>
.add('Demo', () => <Demo/>)
.add('Two hooks on page', () =>
<>
<AnotherComponent />
<Demo />
</>
)
37 changes: 24 additions & 13 deletions src/useLockBodyScroll.ts
Original file line number Diff line number Diff line change
@@ -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;

0 comments on commit 5dd10e9

Please sign in to comment.