React中Material UI Drawer刷新后如何实现滚动到底部?
解决Material UI Drawer触发API请求后滚动位置重置的问题
问题背景
在高级搜索页面使用Material UI Drawer,内置大量复选框和单选按钮,点击时触发API GET请求实时获取结果,但每次请求都会导致Drawer滚动回顶部。由于单选按钮位于Drawer底部,希望点击时强制Drawer滚动到底部,模拟保留原滚动位置。
可行解决方案
方法1:利用useRef+useEffect监听状态变化实现滚动
通过useRef获取Drawer的Paper容器,监听单选按钮的选中状态变化,在组件重渲染完成后执行滚动操作:
import { useRef, useEffect, useState } from 'react'; import Drawer from '@mui/material/Drawer'; import Radio from '@mui/material/Radio'; import RadioGroup from '@mui/material/RadioGroup'; import FormControlLabel from '@mui/material/FormControlLabel'; export default function AdvancedSearchDrawer() { const drawerPaperRef = useRef(null); const [selectedSortMetric, setSelectedSortMetric] = useState(''); // 监听选中状态变化,执行滚动 useEffect(() => { if (drawerPaperRef.current) { drawerPaperRef.current.scrollTop = drawerPaperRef.current.scrollHeight; } }, [selectedSortMetric]); const handleMetricChange = (e) => { const value = e.target.value; setSelectedSortMetric(value); // 触发API请求 fetch(`/api/search?sort=${value}`) .then(res => res.json()) .then(data => { // 处理返回结果 }); }; return ( <Drawer anchor="right" open={true} PaperProps={{ ref: drawerPaperRef, style: { width: 320, overflowY: 'auto' } }} > {/* 其他搜索选项(复选框等) */} <RadioGroup value={selectedSortMetric} onChange={handleMetricChange}> <FormControlLabel value="metric1" control={<Radio />} label="Sorting Metric 1" /> <FormControlLabel value="metric2" control={<Radio />} label="Sorting Metric 2" /> <FormControlLabel value="metric3" control={<Radio />} label="Sorting Metric 3" /> </RadioGroup> </Drawer> ); }
方法2:用requestAnimationFrame延迟滚动操作
如果直接在onChange中执行滚动无效,是因为组件重渲染尚未完成,DOM状态未更新。使用requestAnimationFrame将滚动操作推迟到下一次浏览器渲染周期:
// 给Drawer的Paper添加id <Drawer PaperProps={{ id: 'drawer-paper', style: { width: 320, overflowY: 'auto' } }} > {/* 内容 */} </Drawer> // 单选按钮的onChange处理函数 const handleMetricChange = (e) => { const value = e.target.value; setSelectedSortMetric(value); fetch(`/api/search?sort=${value}`) .then(res => res.json()) .then(data => { /* 处理结果 */ }); // 延迟执行滚动 requestAnimationFrame(() => { const drawerPaper = document.getElementById('drawer-paper'); if (drawerPaper) { drawerPaper.scrollTop = drawerPaper.scrollHeight; } }); };
为什么之前的方法失效?
- 第一种方法报错
Cannot read properties of undefined (reading 'getScrollElement'):Material UI的Drawer并未公开getScrollElement方法,调用内部未暴露的API会导致报错,不要依赖这类非公开接口。 - 第二种方法直接设置滚动无效:滚动操作执行时机过早,组件重渲染还未完成,DOM元素的滚动状态尚未更新,导致滚动指令未生效。
内容的提问来源于stack exchange,提问作者LOTUSMS
相关产品推荐
相关产品推荐

