react-virtualized icon indicating copy to clipboard operation
react-virtualized copied to clipboard

scrollToRow, scrollToPosition no longer works with WindowScroller after updating React to v16.8

Open michchan opened this issue 4 years ago • 10 comments

For my case, I've tested that it works for both methods without a WindowScroller. Any idea what's happening

Please reference this issue: https://github.com/bvaughn/react-virtualized/issues/1179#issuecomment-593502991

What is the current behavior?

Calling scrollToRow and scrollToPosition no longer scrolls properly, but the functions are defined and I can log to the console. It just failed silently.

What is the expected behavior?

It should simply scroll to the right position / row.

Which versions of React and react-virtualized, and which browser / OS are affected by this issue? Did this work in previous versions of react-virtualized?

Browser Chrome v80
OS OSX 10.15.3
React 16.8.5
React DOM 16.8.5
react-virtualized 9.21.2

michchan avatar Mar 03 '20 04:03 michchan

There are multiple open issues related to this same problem, some referencing List/Grid and others referencing WindowScroller. None of the workarounds referenced in all of these issues are working and downgrading react is not a viable solution for us.

Any idea if this is going to be fixed soon?

nicholeuf avatar Mar 09 '20 20:03 nicholeuf

As a quick workaround, this have worked for me - restrict the version to: "react-virtualized": "9.21.1" in package.json. As I noticed the patch version updated had introduced the issue.

fekgab avatar May 08 '20 18:05 fekgab

I have the same problem with this.Are you deal with this problem?

heyouquan avatar Aug 31 '20 03:08 heyouquan

Sorry lads, forgot to post. My quick workaround is like this:

import getScrollYFromElementOrWindow from 'simply-utils/dist/dom/getScrollYFromElementOrWindow';
import tryUntil from 'simply-utils/dist/utils/tryUntil';

...

/*
* Put this as the `ref` prop of the `List` component 
*/
const handleRef = useCallback((ref) => {
    if (ref !== null) {
        /**
         * * TEMP Fix for virtualized list scrollToPosition not working issue when using with WindowScroller
         * 
         * @TODO: Wait for PR
         * Ref: https://github.com/bvaughn/react-virtualized/issues/1179
         */
        if (windowScrollerEnabled) {
            // Override and fix scrollToPosition
            ref.scrollToPosition = (scrollTop: number) => tryUntil(() => {
                // Use the scroll element ref passed from props
                const scrollEl = scrollElementRef?.current
                if (scrollEl) {
                    // Use the `scrollTo` method from the passed element
                    scrollEl.scrollTo({ top: scrollTop })
                    // Get updated scroll top form the element
                    const updatedScrollTop = getScrollYFromElementOrWindow(scrollEl)
                    // Done if targeted scroll top is met (case: true), or
                    // Try next if targeted scroll top is not met (case: false)
                    return updatedScrollTop === scrollTop
                }
                // Try next
                return false
            }, 30, 0)
            // Override and fix scrollToRow
            ref.scrollToRow = (index: number) => {
                const scrollTop = ref.getOffsetForRow({ index })
                ref.scrollToPosition(scrollTop)
            }
        }
    }
}, [scrollElementRef, windowScrollerEnabled])     

Btw, simply-utils is just the open-source npm utils library I created. The tryUntil util is just keep calling the callback until success.

michchan avatar Aug 31 '20 04:08 michchan

Sorry lads, forgot to post. My quick workaround is like this:

import getScrollYFromElementOrWindow from 'simply-utils/dist/dom/getScrollYFromElementOrWindow';
import tryUntil from 'simply-utils/dist/utils/tryUntil';

...

/*
* Put this as the `ref` prop of the `List` component 
*/
const handleRef = useCallback((ref) => {
    if (ref !== null) {
        /**
         * * TEMP Fix for virtualized list scrollToPosition not working issue when using with WindowScroller
         * 
         * @TODO: Wait for PR
         * Ref: https://github.com/bvaughn/react-virtualized/issues/1179
         */
        if (windowScrollerEnabled) {
            // Override and fix scrollToPosition
            ref.scrollToPosition = (scrollTop: number) => tryUntil(() => {
                // Use the scroll element ref passed from props
                const scrollEl = scrollElementRef?.current
                if (scrollEl) {
                    // Use the `scrollTo` method from the passed element
                    scrollEl.scrollTo({ top: scrollTop })
                    // Get updated scroll top form the element
                    const updatedScrollTop = getScrollYFromElementOrWindow(scrollEl)
                    // Done if targeted scroll top is met (case: true), or
                    // Try next if targeted scroll top is not met (case: false)
                    return updatedScrollTop === scrollTop
                }
                // Try next
                return false
            }, 30, 0)
            // Override and fix scrollToRow
            ref.scrollToRow = (index: number) => {
                const scrollTop = ref.getOffsetForRow({ index })
                ref.scrollToPosition(scrollTop)
            }
        }
    }
}, [scrollElementRef, windowScrollerEnabled])     

Btw, simply-utils is just the open-source npm utils library I created. The tryUntil util is just keep calling the callback until success.

Hey Michael! Could you give more details how to use your solution? Maybe some https://codesandbox.io example?

pro2html avatar Sep 02 '21 15:09 pro2html

@pro2html May I know which part you don't understand? It is hard and time consuming for me to recreate a full code example now since it's a bit legacy. And I do recommend you switching to the new package https://github.com/bvaughn/react-window.

michchan avatar Sep 04 '21 05:09 michchan

Thanks for the link, Michael!

I think it will be easier to use the newer version than try to fix the old one.

Thank you for responding to my message, I appreciate it!

4 сент. 2021 г., в 08:57, Michael Chan L. S. @.***> написал(а):

@pro2html https://github.com/pro2html May I know which part you don't understand? It is hard and time consuming for me to recreate a full code example now since it's a bit legacy. And I do recommend you switching to the new package https://github.com/bvaughn/react-window https://github.com/bvaughn/react-window.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/bvaughn/react-virtualized/issues/1507#issuecomment-912915030, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACQ2VSGUFZBCTSXPVETBBRLUAGYLNANCNFSM4LACKL4A. Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

pro2html avatar Sep 04 '21 06:09 pro2html

@pro2html hello, I cannot quite get how to * Put this as the ref prop of the List component * and how to use ref. scrollToRow later.

jessiezhudev avatar Sep 17 '21 08:09 jessiezhudev

@pro2html and can you share the implementation of tryUtil function you're using?

jessiezhudev avatar Sep 17 '21 11:09 jessiezhudev

I use the suggestion of @michchan , here is how I made it work:

 let tableRef = useRef<Table | null>(); // create a ref, so we can calling it in future
 const handleRef = useCallback((ref: Table | null) => {
        if (ref !== null) {
            ref.scrollToPosition = (scrollTop: number) =>
                tryUntil(
                    () => {
                        const scrollEl = window;
                        if (scrollEl) {
                            scrollEl.scrollTo({ top: scrollTop, behavior: 'smooth' });
                            const updatedScrollTop = getScrollYFromElementOrWindow(scrollEl);
                            console.log(updatedScrollTop);
                            return updatedScrollTop === scrollTop;
                        }
                        // Try next
                        return false;
                    },
                    30,
                    0,
                );
            ref.scrollToRow = (index: number) => {
                const scrollTop = ref.getOffsetForRow({ index, alignment: 'center' });
                ref.scrollToPosition(scrollTop);
            };
        }
    }, []);

and in the <Table component I put this in the ref prop:

<Table ref={(ref) => { handleRef(ref); tableRef.current = ref; }} And now we can use the function:

tableRef.current?.scrollToRow(row);

jailsonpaca avatar Mar 07 '23 13:03 jailsonpaca