Skip to content
This repository has been archived by the owner on Jan 5, 2023. It is now read-only.

fix(Carousel): Use event handler instead of useEffect for scroll #683

Merged
merged 6 commits into from
May 24, 2022

Conversation

mayank99
Copy link
Contributor

useEffect was causing problems on React 18 (#656 (review)), so this change reworks the scrolling mechanism to explicitly call scrollTo on every single manual event (clicks, keyboard) as well as when the currentIndex prop changes. It also sets isManuallyUpdating to true.

After that we listen to the 'scroll' event and reset isManuallyUpdating to false after the very last scroll event.

The intersection observer is used for syncing the active dot with scroll events that are triggered natively (e.g. dragging on mobile). We check for isManuallyUpdating here to avoid messing with manual scrollTo calls.

useEffect was causing problems on React 18, so this change reworks the scrolling mechanism to explicitly call `scrollTo` on every single manual event (clicks, keyboard) as well as when the `currentIndex` prop changes. It also sets `isManuallyUpdating` to true.

After that we listen to the 'scroll' event and reset `isManuallyUpdating` to false after the very last scroll event.

The intersection observer is used for syncing the active dot with scroll events that are triggered natively (e.g. dragging on mobile). We check for `isManuallyUpdating` here to avoid messing with manual `scrollTo` calls.
@mayank99 mayank99 requested a review from a team as a code owner May 20, 2022 16:03
@mayank99 mayank99 requested review from a team, veekeys and elephantcatdog and removed request for a team May 20, 2022 16:03
Comment on lines 83 to 85
scrollTimeout.current = window.setTimeout(() => {
isManuallyUpdating.current = false;
}, 100);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the only part that I'm not sure about. I had to do this because there is no scrollend event. To make things worse, React doesn't support passive scroll events, which is the recommended approach.

But at least the delay doesn't cause any usability problems (in my testing).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldnt IntersectionObserver help here? You could know, when element is fully visible (so assume scoll has ended)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how would it work? we already use intersection observers and this code is directly interacting with it

packages/iTwinUI-react/src/core/Carousel/Carousel.tsx Outdated Show resolved Hide resolved
packages/iTwinUI-react/src/core/Carousel/Carousel.tsx Outdated Show resolved Hide resolved
Comment on lines 83 to 85
scrollTimeout.current = window.setTimeout(() => {
isManuallyUpdating.current = false;
}, 100);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldnt IntersectionObserver help here? You could know, when element is fully visible (so assume scoll has ended)

Copy link
Member

@veekeys veekeys left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works,
I dont like timeout, but we can revisit it later, if issues appear.

@mayank99 mayank99 enabled auto-merge (squash) May 24, 2022 13:36
@mayank99 mayank99 merged commit bcf125b into main May 24, 2022
@mayank99 mayank99 deleted the mayank/carousel-scroll branch May 24, 2022 13:43
mayank99 added a commit to iTwin/iTwinUI that referenced this pull request Dec 21, 2022
…in/iTwinUI-react#683)

useEffect was causing problems on React 18, so this change reworks the scrolling mechanism to explicitly call scrollTo on every single manual event (clicks, keyboard) as well as when the currentIndex prop changes. It also sets isManuallyUpdating to true. And then we listen to the 'scroll' event and reset isManuallyUpdating to false after the very last scroll event.

The intersection observer is used for syncing the active dot with scroll events that are triggered natively (e.g. dragging on mobile). We check for isManuallyUpdating here to avoid messing with manual scrollTo calls.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants