React-select: Compatibility issue with react-custom-scrollbars

Created on 30 Sep 2020  路  5Comments  路  Source: JedWatson/react-select

Trying to use react-custom-scrollbars inside a custom MenuList component makes the keyboard navigation of react-select break.

Example:

// CustomMenuList.tsx
import React from "react";
import { components } from "react-select";
import { Scrollbars } from "react-custom-scrollbars";
import styled from "styled-components";

export const MenuList = (props: any) => {
  return (
    <components.MenuList {...props}>
      <div style={{ height: 200 }}>
        <Scrollbars>
          {props.children}
        </Scrollbars>
      </div>
    </components.MenuList>
  );
};
// App.tsx
<Select 
  components={{ MenuList }}
  captureMenuScroll={false} // custom scrollbar doesn't scroll if this is true
/>

With the above code, the dropdown list no longer scrolls to the focused option when trying to navigate using the keyboard arrow keys. However, if we remove the <Scrollbars> component, then the keyboard navigation works as expected and the menu starts scrolling as we press the down arrow key repeatedly.

awaiting-author-response

Most helpful comment

@cseas @kabdelkareem

The Select component requires a ref to the scrollable container of the options list to scroll to the focused option. The MenuList component receives for this the innerRef prop.

But we can麓t just simply set the ref prop on the Scrollbars component, because this would be a reference to the component, not the actual DOM element.

For this we would have to do as follows:

const MenuList = ({ children, innerRef, ...props }) => {
  const intermediateRef = React.useRef();

  React.useEffect(() => {
    innerRef(intermediateRef.current ? intermediateRef.current.view : null);
  }, [innerRef, intermediateRef]);

  return (
    <components.MenuList {...props}>
      <div style={{ height: 200 }}>
        <Scrollbars ref={intermediateRef}>{children}</Scrollbars>
      </div>
    </components.MenuList>
  );
};

At first we need the reference to the Scrollbars component. It contains a reference to the needed DOM element. Then as soon as the reference exists we set the reference to the scrolling DOM element as our innerRef reference.

All 5 comments

I am facing the same issue using version in package.json
"react-select": "^3.1.1",
"react-custom-scrollbars": "^4.2.1",

@cseas @kabdelkareem

The Select component requires a ref to the scrollable container of the options list to scroll to the focused option. The MenuList component receives for this the innerRef prop.

But we can麓t just simply set the ref prop on the Scrollbars component, because this would be a reference to the component, not the actual DOM element.

For this we would have to do as follows:

const MenuList = ({ children, innerRef, ...props }) => {
  const intermediateRef = React.useRef();

  React.useEffect(() => {
    innerRef(intermediateRef.current ? intermediateRef.current.view : null);
  }, [innerRef, intermediateRef]);

  return (
    <components.MenuList {...props}>
      <div style={{ height: 200 }}>
        <Scrollbars ref={intermediateRef}>{children}</Scrollbars>
      </div>
    </components.MenuList>
  );
};

At first we need the reference to the Scrollbars component. It contains a reference to the needed DOM element. Then as soon as the reference exists we set the reference to the scrolling DOM element as our innerRef reference.

Greetings @cseas @kabdelkareem,

Can you confirm that the above solution works for you and if so close the ticket?

My team figured that a custom JavaScript scrollbar isn't the best idea and we'd like to use the native one. So we just added the following styles to menuList so at least the scrollbar is styled on webkit browsers:

"::-webkit-scrollbar": {
    width: "0.6rem",
  },
  "::-webkit-scrollbar-track": {
    background: "rgba(0, 0, 0, 0)", // transparent
    borderRadius: "1rem",
  },
  "::-webkit-scrollbar-thumb": {
    background: state.theme.colors.primary25,
    borderRadius: "1rem",
    boxShadow: "inset 0 0 0.6rem rgba(0, 0, 0, 0.2)",
  },
  "::-webkit-scrollbar-thumb:hover": {
    background: Color.silver,
  }

Full example here.

Maybe @kabdelkareem can confirm whether the above solution using ref works for their use case? I'll close the Issue for now.

@cseas I have tried it and it is working. thanks @Rall3n

Was this page helpful?
0 / 5 - 0 ratings