Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OverlayScrollbars stopped working with React Virtuoso #506

Closed
justasdev opened this issue Feb 28, 2023 · 5 comments
Closed

OverlayScrollbars stopped working with React Virtuoso #506

justasdev opened this issue Feb 28, 2023 · 5 comments
Labels
🍌 question react Issue has a connection to the React framework. 💦 Virtualization Issue has a connection with a scroll virtualization library.

Comments

@justasdev
Copy link

justasdev commented Feb 28, 2023

Describe the bug

We're using OverlayScrollbars as custom scroller for react virtuoso. Upgraded OverlayScrollbars to 2.1 and it stopped working with react virtuoso.

To Reproduce

Looks like scrollbarsRef.osInstance()?.elements().viewport is null at the time when virtuoso initializes scroller. Tried upgrading virtuoso too - same issue. osInstance is initialized, but elements() returns object with null values. Same issue when using hook based approach instead of react component.

Expected behavior

scrollbarsRef.osInstance()?.elements().viewport should not be null when virtuoso initializes scroller. Like it was in pre 2.0 versions.

@KingSora
Copy link
Owner

Good day @justasdev :)

Please share a minimal reproducable example of how your code looks.. You can use codesandbox, stackblitz or jsfiddle for that. I can then take a look where the problem lies

@ippowe
Copy link

ippowe commented Mar 7, 2023

Hello @justasdev,
I also faced the same issue as you. Below is the code I used to solve the problem.

import React, { CSSProperties, PropsWithChildren, useCallback } from "react";
import { OverlayScrollbarsComponent } from "overlayscrollbars-react";

type Props = PropsWithChildren<{
  className?: string;
  style?: CSSProperties;
}>;

const CustomScrollbar = React.forwardRef<any, Props>(
  ({ children, className, style, ...props }, ref) => {
    const refSetter = useCallback(
      (scrollbarsRef: any) => {
        if (ref && scrollbarsRef) {
          const instance = scrollbarsRef.osInstance();
          if (typeof ref === "function") return; // type narrowing for ForwaredRef
          if (!instance) {
            ref.current = scrollbarsRef.getElement();
          } else {
            const viewport = instance.elements().viewport as HTMLElement;
            Object.entries(props).forEach(([key, value]) => {
              if (key.startsWith("data-")) {
                viewport.setAttribute(key, value as string);
              }
            });
            ref.current = viewport;
          }
        }
      },
      [ref, props]
    );

    return (
      <OverlayScrollbarsComponent ref={refSetter} className={className} style={style} {...props}>
        {children}
      </OverlayScrollbarsComponent>
    );
  }
);

The root cause of the issue appears to be that the osInstance method returned null during the initial rendering, which was passed through the ref props of the OverlayscrollbarsComponent. Therefore, I temporarily use another method, getElement, which is available in scrollbarRef before osInstance provides the correct value, and it worked. I'm not sure if this is a fundamental solution, but it worked well in my situation. Hope this helps!

@KingSora
Copy link
Owner

KingSora commented Mar 7, 2023

@ippowe thanks for your suggestion! :)

I had some time to take a look and came up with a good solution. OverlayScrollbars v2 was build with virtual scrolling libraries in mind and should generally work with all of them.. The useOverlayScrollbars hook in particular is a very handy tool in those cases.

List: https://codesandbox.io/s/sandpack-project-forked-2nhuwb?file=/App.js
Table: https://codesandbox.io/s/sandpack-project-forked-5uhg9t?file=/App.js

In the example I've used deferred initialization, in case this is not desired you can just remove the { defer: true } option from the hook. The solution could be used with Grid and Table and you can use the same logic to migrate to other virtual scrolling libraries in case you need it.

@KingSora KingSora added 🍌 question react Issue has a connection to the React framework. labels Mar 7, 2023
@KingSora
Copy link
Owner

@justasdev I'll close this issue for now. In case my solution doesn't work for you please feel free to re-open this issue or create a new one. :)

@KingSora KingSora added the 💦 Virtualization Issue has a connection with a scroll virtualization library. label Oct 19, 2023
@KingSora
Copy link
Owner

Related: #639

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🍌 question react Issue has a connection to the React framework. 💦 Virtualization Issue has a connection with a scroll virtualization library.
Projects
None yet
Development

No branches or pull requests

3 participants