使用simplebar-react时滚动条可见状态无法更新的问题
解决simplebar-react滚动条可见状态不更新的问题
你的问题出在两个核心点:一是仅在组件挂载时执行了一次状态判断,没有监听后续内容变化、容器尺寸调整或滚动行为;二是判断逻辑错误,hidden属性并非simplebar滚动条可见性的正确判断依据。
下面是修正后的自定义Hook,可实时同步滚动条的可见状态:
import { useState, useRef, useLayoutEffect } from 'react'; export const useIsScrollbarVisible = () => { const [isScrollbarVisible, setIsScrollbarVisible] = useState(false); const scrollbarRef = useRef<HTMLElement>(null); const observerRef = useRef<MutationObserver | null>(null); // 判断滚动条可见性的核心逻辑 const checkScrollbarVisibility = () => { const element = scrollbarRef.current; if (!element) return; // 垂直滚动条判断:内容总高度 > 容器可视高度 const hasVerticalScrollbar = element.scrollHeight > element.clientHeight; // 若需判断水平滚动条,替换为 element.scrollWidth > element.clientWidth setIsScrollbarVisible(hasVerticalScrollbar); }; useLayoutEffect(() => { const element = scrollbarRef.current; if (!element) return; // 初始化时先检查一次 checkScrollbarVisibility(); // 绑定滚动、窗口尺寸变化监听 const handleScroll = checkScrollbarVisibility; const handleResize = checkScrollbarVisibility; element.addEventListener('scroll', handleScroll); window.addEventListener('resize', handleResize); // 监听内容DOM变化(如新增/删除节点、内容高度调整) observerRef.current = new MutationObserver(checkScrollbarVisibility); observerRef.current.observe(element, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); // 组件卸载时清理所有监听,避免内存泄漏 return () => { element.removeEventListener('scroll', handleScroll); window.removeEventListener('resize', handleResize); observerRef.current?.disconnect(); }; }, []); return { scrollbarRef, isScrollbarVisible }; };
使用方式
你的原有调用逻辑无需大幅修改,scrollableNodeProps绑定ref的方式是正确的:
const { isScrollbarVisible, scrollbarRef } = useIsScrollbarVisible(); <Scrollbar scrollableNodeProps={{ ref: scrollbarRef }}> <Box {...(isScrollbarVisible && { pr: 3 })}> {/* 你的内容区域 */} </Box> </Scrollbar>
关键优化说明
- 实时触发更新:覆盖了滚动操作、窗口尺寸变化、内容DOM修改三类会影响滚动条状态的场景
- 精准判断逻辑:通过容器内容高度与可视高度的对比,准确判断滚动条是否需要显示
- 副作用清理:组件卸载时自动移除所有监听和观察者,避免内存泄漏
内容的提问来源于stack exchange,提问作者goscamp
相关产品推荐
相关产品推荐

