React useBodyScrollLock hook

React, Hooks, Effect · Sep 2, 2021

Enables body scroll locking.

  • Use the useLayoutEffect() with an empty array as the second argument to execute the provided callback only once when the component is mounted.
  • Use Window.getComputedStyle() to get the overflow value of the body element and store it in a variable.
  • Replace the overflow value of the body element with 'hidden' and restore it to its original value when unmounting.
const useBodyScrollLock = () => {
  React.useLayoutEffect(() => {
    const originalStyle = window.getComputedStyle(document.body).overflow;
    document.body.style.overflow = 'hidden';
    return () => (document.body.style.overflow = originalStyle);
  }, []);
};
const Modal = ({ onClose }) => {
  useBodyScrollLock();

  return (
    <div
      style={{
        zIndex: 100, background: 'rgba(0,0,0,0.25)', display: 'flex',
        justifyContent: 'center', alignItems: 'center'
      }}
    >
      <p
        style={{ padding: 8, borderRadius: 8, background: '#fff' }}
        onClick={onClose}
      >
        Scroll locked! <br /> Click me to unlock
      </p>
    </div>
  );
};

const MyApp = () => {
  const [modalOpen, setModalOpen] = React.useState(false);

  return (
    <div
      style={{
        height: '400vh', textAlign: 'center', paddingTop: 100,
        background: 'linear-gradient(to bottom, #1fa2ff, #12d8fa, #a6ffcb)'
      }}
    >
      <button onClick={() => setModalOpen(true)}>Open modal</button>
      {modalOpen && <Modal onClose={() => setModalOpen(false)} />}
    </div>
  );
};

ReactDOM.render(<MyApp />, document.getElementById('root'));

Written by Angelos Chalaris

I'm Angelos Chalaris, a JavaScript software engineer, based in Athens, Greece. The best snippets from my coding adventures are published here to help others learn to code.

If you want to keep in touch, follow me on GitHub or Twitter.

More like this