Skip to content

Instantly share code, notes, and snippets.

@gragland
Last active October 11, 2019 17:49
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gragland/f50690d2724aec1bd513de8596dcd9b9 to your computer and use it in GitHub Desktop.
Save gragland/f50690d2724aec1bd513de8596dcd9b9 to your computer and use it in GitHub Desktop.
import { useState, useLayoutEffect } from 'react';
// Usage
function App(){
// State for our modal
const [modalOpen, setModalOpen] = useState(false);
return (
<div>
<button onClick={() => setModalOpen(true)}>Show Modal</button>
<Content />
{modalOpen && (
<Modal
title="Try scrolling"
content="I bet you you can't! Muahahaha 😈"
onClose={() => setModalOpen(false)}
/>
)}
</div>
);
}
function Modal({ title, content, onClose }){
// Call hook to lock body scroll
useLockBodyScroll();
return (
<div className="modal-overlay" onClick={onClose}>
<div className="modal">
<h2>{title}</h2>
<p>{content}</p>
</div>
</div>
);
}
// Hook
function useLockBodyScroll() {
useLayoutEffect(() => {
// Get original value of body overflow
const originalStyle = window.getComputedStyle(document.body).overflow;
// Prevent scrolling on mount
document.body.style.overflow = 'hidden';
// Re-enable scrolling when component unmounts
return () => document.body.style.overflow = originalStyle;
}, []); // Empty array ensures effect is only run on mount and unmount
}
@dallanlee
Copy link

dallanlee commented Oct 11, 2019

I took a shot at modifying this to make it work:

  1. On iOS
  2. When multiple "instances" of lockBodyScroll (modals in this case) are active

It seems to be working with my changes in my sandbox fork here: https://codesandbox.io/s/uselockbodyscroll-example-mq9rm.
Or test it on your iOS device here: https://mq9rm.csb.app/

But I'm pretty new to custom hooks (and programming, really) so I'm open to suggestions/critique 👍🏼

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment