You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React中让自定义SelectBox打开时滚动到选中项?

实现SelectBox打开时自动滚动到已选中选项

核心实现思路

当SelectBox展开时,找到已选中的选项DOM元素,调用scrollIntoView()方法将其滚动到可视区域。通过监听展开状态的变化,在状态切换为展开时执行滚动逻辑。

修改后的完整代码

import { useState, useCallback, useEffect, useRef } from 'react';
import cx from 'classnames';

const CustomSelectBox = ({ options, onChange }: { options: string[], onChange: (value: string) => void }) => {
  const [selectedOption, setSelectedOption] = useState<string>('');
  const [isOpenOption, setIsOpenOption] = useState<boolean>(false);
  const listRef = useRef<HTMLUListElement>(null);

  const handleToggle = useCallback((e) => {
    e.preventDefault();
    setIsOpenOption(prev => !prev);
  }, []);

  const handleSelect = useCallback(
    (e, option: string) => {
      e.preventDefault();
      if (option !== selectedOption) {
        setSelectedOption(option);
        onChange(option);
      }
      setIsOpenOption(false);
    },
    [selectedOption, onChange],
  );

  // 监听展开状态,滚动到选中项
  useEffect(() => {
    if (isOpenOption && selectedOption) {
      const selectedElement = listRef.current?.querySelector('[aria-selected="true"]');
      if (selectedElement) {
        selectedElement.scrollIntoView({
          behavior: 'smooth',
          block: 'center',
        });
      }
    }
  }, [isOpenOption, selectedOption]);

  return (
    <div className={'select'}>
      {/* 展开/收起触发按钮 */}
      <button onClick={handleToggle} className="select-trigger">
        {selectedOption || '请选择'}
      </button>
      
      {isOpenOption && (
        <ul 
          ref={listRef}
          className={cx('list')} 
          role="listbox"
          style={{ maxHeight: '200px', overflowY: 'auto' }}
        >
          {options.map((option, index) => (
            <li key={`${option}-${index}`} className={'item'}>
              <a
                role="option"
                className={cx('option', { selected: option === selectedOption })}
                aria-selected={option === selectedOption}
                onClick={event => handleSelect(event, option)}
              >
                {option}
              </a>
            </li>
          ))}
        </ul>
      )}
    </div>
  );
};

export default CustomSelectBox;

关键步骤说明

  1. 添加列表容器Ref:用useRef获取滚动列表的<ul>元素,方便后续查询子元素。
  2. 监听展开状态:通过useEffect监听isOpenOption和selectedOption的变化,仅在SelectBox展开且存在选中项时执行滚动操作。
  3. 执行滚动逻辑:通过querySelector找到带有aria-selected="true"的选中项,调用scrollIntoView()实现滚动。可通过配置参数调整滚动平滑度和元素对齐方式(比如居中显示)。
  4. 完善基础结构:补充了展开/收起的触发按钮,确保组件功能完整;优化了列表项的key值,避免重复选项导致的渲染异常。

注意事项

  • 必须给滚动列表设置overflow-y: auto和固定高度(如maxHeight),否则不会出现滚动条,滚动逻辑无效。
  • 如果选项存在重复值,key需结合option和index生成,避免React渲染警告。

内容的提问来源于stack exchange,提问作者user3871177

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 05:03:37