如何将 onScroll 处理程序添加到 react-select 组件的 menuList?

How do I add an onScroll handler to the menuList of a react-select component?

我想将 onScroll 处理程序添加到 react-select 组件的 menuList,但以下内容不起作用。我怀疑我需要为其中一个子项设置 onScroll 而不是包含子项的元素,但我不知道该怎么做。

import React from 'react';

import Select, { components, MenuListProps } from 'react-select';
import {
  ColourOption,
  colourOptions,
  FlavourOption,
  GroupedOption,
  groupedOptions,
} from './docs/data';


const handleScroll = () =>{
  console.log('scrolling')
}

const MenuList = (
  props: MenuListProps<ColourOption | FlavourOption, false, GroupedOption>
) => {
  return (
    <components.MenuList {...props}>
      <div onScroll={handleScroll}>
        {props.children}
      </div>
    </components.MenuList>
  );
};

export default () => (
  <Select<ColourOption | FlavourOption, false, GroupedOption>
    defaultValue={colourOptions[1]}
    menuIsOpen={true}
    options={groupedOptions}
    components={{ MenuList }}
  />
);

https://codesandbox.io/s/codesandboxer-example-forked-jr74k?file=/example.tsx:0-721

我也试过用这样的东西

mySelectRef.current.menuListRef.addEventListener("scroll", handleScroll)

.current.current.menuListRef 在执行命令时始终未定义或为空。我尝试使用 React.useEffect 和 setTimeout,但效果不佳。我希望我可以通过设置右内部 div.

onScroll 来完成此操作

理由

理想情况下,您不会从头开始实现自定义处理程序,而是重用或从已经存在并由开源社区维护的挂钩开始。

当你自己实现它时,有一些注意事项,比如事件监听器必须是被动的,你必须使用 React 的 useEffect 钩子注册和注销监听器。

例子

有很多这样的例子。一个可能是 implementation from react-use.

实施

您的组件可能如下所示:

const Component = () => {
  const ref = useRef();

  const { x, y } = useScroll(ref);

  return <MyComponent ref={ref} />
}

您需要用 div 包装您的 MenuList 组件并向此组件提供 ref,然后访问此 HTML 的直接 div 子级零件。然后你可以为这个元素定义onscroll函数。

const MenuList = (
  props: MenuListProps<ColourOption | FlavourOption, false, GroupedOption>
) => {
  const menuListRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (menuListRef.current) {
      menuListRef.current.querySelector("div").onscroll = () => {
        console.log("scrolling");
      };
    }
  }, [menuListRef]);

  return (
    <div ref={menuListRef}>
      <components.MenuList {...props}>
        <div>{props.children}</div>
      </components.MenuList>
    </div>
  );
};

方法

我试图找出是否可以访问已经支持 onScroll 属性 的本机包装器元素。如果深入研究 components documentation,您会发现 Menu 组件接受 innerProps,这是每个 HTML 元素接受的常规 HTMLAttributes。所以我所做的是提供一个 onScroll 属性 到 innerProps.

代码

const Menu = (
  props: MenuProps<ColourOption | FlavourOption, false, GroupedOption>
) => {
  const handleScroll = () => {
    console.log("scrolling");
  };

  return (
    <components.Menu
      {...props}
      innerProps={{ ...props.innerProps, onScroll: handleScroll }}
    >
      {props.children}
    </components.Menu>
  );
};

export default () => (
  <Select<ColourOption | FlavourOption, false, GroupedOption>
    defaultValue={colourOptions[1]}
    menuIsOpen={true}
    options={groupedOptions}
    components={{ Menu }}
  />
);

工作示例