如何在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;
关键步骤说明
- 添加列表容器Ref:用
useRef获取滚动列表的<ul>元素,方便后续查询子元素。 - 监听展开状态:通过
useEffect监听isOpenOption和selectedOption的变化,仅在SelectBox展开且存在选中项时执行滚动操作。 - 执行滚动逻辑:通过
querySelector找到带有aria-selected="true"的选中项,调用scrollIntoView()实现滚动。可通过配置参数调整滚动平滑度和元素对齐方式(比如居中显示)。 - 完善基础结构:补充了展开/收起的触发按钮,确保组件功能完整;优化了列表项的
key值,避免重复选项导致的渲染异常。
注意事项
- 必须给滚动列表设置
overflow-y: auto和固定高度(如maxHeight),否则不会出现滚动条,滚动逻辑无效。 - 如果选项存在重复值,
key需结合option和index生成,避免React渲染警告。
内容的提问来源于stack exchange,提问作者user3871177
相关产品推荐
相关产品推荐

