react-infinite-scroll-component与MUI Autocomplete滚动联动异常问题
问题:MUI Autocomplete结合InfiniteScroll时scrollableTarget未触发滚动事件
已正确配置InfiniteScroll的hasMore与next方法,但滚动MUI Autocomplete下拉列表时,滚动事件未触发,推测问题出在滚动目标设置上,组件代码如下:
<InfiniteScroll dataLength={patientData.length} next={getMorePatients} hasMore={hasMore} endMessage={<h4>End of List</h4>} scrollableTarget="patient-auto-complete" > <Autocomplete id="patient-auto-complete" options={patientData} value={patient} filterOptions={filterOptionsPatientList} onChange={handlePatientChange} renderOption={(props, option) => { return ( <li {...props} key={option.id} value={option.id}> {(option.firstName === option.lastName ? option.firstName : option.firstName + " " + option.lastName ).replace(null, "")} </li> ); }} renderInput={(params) => <TextField {...params} label="Patient" />} disabled={formMode === "edit_meeting"} sx={{ borderBottom: errorPatient ? 2 : 0, borderColor: errorPatient ? "error.main" : null, }} /> </InfiniteScroll>;
问题根源
MUI Autocomplete的下拉列表容器(Listbox)并非Autocomplete本身的DOM节点,而是通过Popper组件动态生成并挂载到body标签下的独立元素。你当前把scrollableTarget设为Autocomplete的id,实际上监听的是输入框所在容器的滚动,而非下拉列表的滚动,自然不会触发加载逻辑。
解决方案
方法1:通过ListboxProps绑定下拉列表的ref
使用useRef获取Autocomplete下拉列表的实际DOM元素,将其作为scrollableTarget传入InfiniteScroll(部分InfiniteScroll库支持直接传入DOM元素,若仅支持id,可给Listbox手动设置id)。
修改后的代码示例:
import { useRef } from 'react'; import InfiniteScroll from 'react-infinite-scroll-component'; import Autocomplete from '@mui/material/Autocomplete'; import TextField from '@mui/material/TextField'; // 其他组件逻辑 const listboxRef = useRef(null); return ( <> <Autocomplete id="patient-auto-complete" options={patientData} value={patient} filterOptions={filterOptionsPatientList} onChange={handlePatientChange} renderOption={(props, option) => { return ( <li {...props} key={option.id} value={option.id}> {(option.firstName === option.lastName ? option.firstName : `${option.firstName} ${option.lastName}` ).replace(null, "")} </li> ); }} renderInput={(params) => <TextField {...params} label="Patient" />} disabled={formMode === "edit_meeting"} sx={{ borderBottom: errorPatient ? 2 : 0, borderColor: errorPatient ? "error.main" : null, }} // 给下拉列表绑定ref和自定义id ListboxProps={{ ref: listboxRef, id: 'patient-autocomplete-listbox' }} /> <InfiniteScroll dataLength={patientData.length} next={getMorePatients} hasMore={hasMore} endMessage={<h4>End of List</h4>} // 若库支持DOM元素则传ref.current,否则传自定义id scrollableTarget={listboxRef.current || 'patient-autocomplete-listbox'} /> </> );
方法2:使用useAutocomplete hook获取Listbox元素
通过MUI提供的useAutocomplete hook,可以直接获取内部的Listbox DOM节点,无需手动绑定ref:
import { useAutocomplete } from '@mui/material/Autocomplete'; // 其他组件逻辑 const { listboxRef } = useAutocomplete({ options: patientData, value: patient, onChange: handlePatientChange, // 其他配置项 }); // 将listboxRef.current传给InfiniteScroll的scrollableTarget <InfiniteScroll // 其他配置 scrollableTarget={listboxRef.current} />
关键注意点
- 必须确保InfiniteScroll监听的是下拉列表的滚动容器(即MUI Autocomplete的Listbox元素),而非Autocomplete的根节点。
- 若InfiniteScroll仅支持id作为
scrollableTarget,需给Listbox手动设置唯一id。 - 保证
dataLength对应已加载的patientData长度,next方法能正确触发数据加载并更新patientData。
内容的提问来源于stack exchange,提问作者Malinda Peiris
相关产品推荐
相关产品推荐

