Skip to content

Double gap compensation when transitioning between scroll-locked components #84

@cozy-kwon

Description

@cozy-kwon

When one scroll-locked component unmounts and another mounts in the same React batch (e.g. switching modals), body gets both padding-right: 15px and margin-right: 15px — doubling the scrollbar compensation.

With a single modal it works fine (margin-right: 15px only).

The cause: useMemo runs during render, before the previous lock's cleanup effect. So getOffset('margin') reads the lock-applied margin-right: 15px as if it were the original body margin, and getStyles preserves it as padding-right.

// Two modals switching in the same batch
const [modal, setModal] = useState<'A' | 'B'>('A');

{modal === 'A' && <RemoveScroll><ModalA onSwitch={() => setModal('B')} /></RemoveScroll>}
{modal === 'B' && <RemoveScroll><ModalB /></RemoveScroll>}

This is similar to theKashey/react-remove-scroll#71 (fixed via useStateuseMemo), but that fix doesn't cover the batched mount/unmount case — the useMemo still reads contaminated computed styles.

A possible fix: cache the gap measurement and skip re-measurement when data-scroll-locked is already present.

  • react-remove-scroll-bar: 2.3.8
  • React 18.2.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions