react-flip-toolkit icon indicating copy to clipboard operation
react-flip-toolkit copied to clipboard

Problems with scroll in list-detail components

Open manelio opened this issue 4 years ago • 1 comments

I know there are several issues about scrolling already resolved. But I think mine is a different case:

Scenario:

A component ItemsList and a component ItemView, conditionally shown one or another depending on wether an item is selected.

Mobile screen: from the second item some scroll is always needed to reach it.

Content of ItemView is larger than the screen height.

Problem:

For the first and second item (scroll = 0) there's no problem.

For the next items, there are two problems:

  1. The content of item view is shown initially scrolled, so the beginning of the content is initially hidden. If I do a window.scrollTo(0, 0) before or after the state change, the calculation of distance is higher than needed (the effect is the item comes from the hidden bottom of the page).
  2. When I go back to the list, the scroll is not restored.

If you need a CodeSandbox I could prepare one.

manelio avatar Jun 27 '21 19:06 manelio

I'm still facing this problem. I created a very small CodeSandbox here:

https://codesandbox.io/s/react-flip-toolkit-scroll-issue-d5csk

I have been reading the code and I'm pretty convinced the problem comes from the fact componentDidUpdate calls onFlipKeyUpdate (flip-toolkit package) which synchronously calls

  var flippedElementPositionsAfterUpdate = getFlippedElementPositionsAfterUpdate({
    element: containerEl,
    portalKey: portalKey
  });

Here, the bounding client rect is calculated from top of page, because the scroll is still at top before the useEffect was executed:

useEffect(() => !selected && window.scrollTo(0, scrollPosition), [
    selected,
    scrollPosition
  ]);

I'm trying to move the getFlippedElementPositionsAfterUpdate logic to somewhere I can control, so the animation only starts on demand and calculation is executed once the scroll was restored, but it's being a bit frustrating.

If anyone can give some clue or direction would be great.

I have been playing with handleEnterUpdateDelete, but flippedElementPositionsAfterUpdate are calculated at componentDidUpdate time.

I realized adding a setTimeout in Flipper componentDidUpdate:

  componentDidUpdate(
    prevProps: FlipperProps,
    _prevState: any,
    cachedData: FlippedElementPositionsBeforeUpdateReturnVals
  ) {
    if (this.props.flipKey !== prevProps.flipKey && this.el) {
      setTimeout(() => {
        onFlipKeyUpdate(...)
      })
    }
  }

makes the bounding client rect calculation right, but I'm sure that's a very dirty patch and also creates a small glitch on animation start.

manelio avatar Dec 30 '21 10:12 manelio