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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 09:25:04