A scrollable panel shows a header that pins once the user scrolls past one threshold and unpins once they scroll back past a lower one. After pinning once, the header never returns to unpinned no matter how far back up the panel is scrolled.
Scrolling down past the pin threshold correctly shows "Header is pinned". Scrolling back up past the unpin threshold never changes it back to "Header is unpinned" - the header stays pinned permanently.
Think about when the scroll listener was created and what value of pinned it has remembered ever since.
Think about when the scroll listener was created and what value of pinned it has remembered ever since.
Why this fixes it
`handleScroll` closed over `pinned` at the moment the effect first ran, and because the dependency array was empty, React never recreated the listener. Every scroll event for the rest of the component's life checked the same stale `false` value captured at mount - the unpin branch was unreachable because `pinned` inside the closure was always `false`, so the condition `pinned && panel.scrollTop < 50` could never be true. Adding `pinned` to the dependency array tells React to remove the old listener and attach a fresh one whenever `pinned` changes, so `handleScroll` always closes over the current value and both branches remain reachable.