【问题标题】:How do I add an onScroll handler to the menuList of a react-select component?如何将 onScroll 处理程序添加到 react-select 组件的 menuList?
【发布时间】:2021-12-29 11:35:04
【问题描述】:

我想在 react-select 组件的 menuList 中添加一个 onScroll 处理程序,但以下内容不起作用。我怀疑我需要为其中一个孩子设置 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 来完成此操作。

【问题讨论】:

    标签: reactjs react-select


    【解决方案1】:

    您需要用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>
      );
    };
    

    【讨论】:

    • 谢谢。这达到了既定目标。我有一些新问题要解决。我应该提到我正在重构以下站点的代码以使用 redux 和 React 挂钩并将我的顶级组件从类样式切换到函数样式。它具有根据另一个列表的滚动位置控制滚动位置的代码,以及对用户滚动该列表做出反应的其他代码。它需要在滚动位置和输入更改时计算 react-select 中的粘性顶部和底部标题。 rfr-resources.netlify.app
    【解决方案2】:

    基本原理

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

    在自己实现时,有一些注意事项,例如事件侦听器必须是被动的,并且您必须使用 React 的 useEffect 钩子注册和取消注册侦听器。

    示例

    那里有很多例子。一个可能是来自react-use 的implementation。

    实施

    您的组件可能如下所示:

    const Component = () => {
      const ref = useRef();
    
      const { x, y } = useScroll(ref);
    
      return <MyComponent ref={ref} />
    }
    

    【讨论】:

    • 我不知道从这里做什么。事件侦听器被动是什么意思,我该如何做到这一点?
    • 如果您使用现成的解决方案,例如示例,您不必担心这些实现细节。我列出的示例已经在后台使用了被动。您的问题在这里得到解答:stackoverflow.com/questions/37721782/…
    【解决方案3】:

    方法

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

    代码

    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 }}
      />
    );
    

    工作示例

    【讨论】:

    • 谢谢。我不知道为什么,但这在我的实际情况下不起作用。奇怪。
    • 这很奇怪。出于某种原因,在我的应用程序中,我可以添加“onClick”处理程序,但不能添加“onScroll”处理程序。我在我的应用程序上尝试了另一个 react-select 并遇到了同样的问题。但是在您的代码框一中它工作正常。
    • 好的。我通过使用 MenuList 而不是 Menu 进行基本相同的操作来使其工作。我仍然不明白为什么它会像您在代码框案例中那样工作,但在我的案例中却没有。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-03
    • 2017-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-05
    • 1970-01-01
    相关资源
    最近更新 更多