Scrollable check in useEffect does not work on page refresh

huangapple go评论62阅读模式
英文:

Scrollable check in useEffect does not work on page refresh

问题

以下是您要翻译的代码部分:

const [isScrollableLeft, setIsScrollableLeft] = useState(false);
const [isScrollableRight, setIsScrollableRight] = useState(false);
const listRef = useRef();

useEffect(() => {
    const checkScrollable = () => {
        if (listRef.current) {
            const { scrollLeft, scrollWidth, clientWidth } = listRef.current;
            setIsScrollableLeft(scrollLeft > 0);
            setIsScrollableRight(scrollWidth > clientWidth + scrollLeft);
        }
    };

    if (listRef.current) {
        listRef.current.addEventListener("scroll", checkScrollable);
        // Initial check
        checkScrollable();
    }

    // Clean up the event listener when the component is unmounted
    return () => {
        if (listRef.current) {
            listRef.current.removeEventListener("scroll", checkScrollable);
        }
    };
}, []);
<div className="community-overall-link-container">
    {isScrollableLeft && <div className="link-container-arrow arrow-left-main" onClick={scrollToStart}><img src={leftDirection} alt="←" /></div>}
    <ul ref={listRef} className="community-links-container">
        <li className={`community-links-item ${communityLink === 1 ? 'community-links-item-active' : ''}`} onClick={() => setCommunityLink(1)}>Upcoming Hangout</li>
        <li className={`community-links-item ${communityLink === 2 ? 'community-links-item-active' : ''}`} onClick={() => setCommunityLink(2)}>Discussions</li>
        <li className={`community-links-item ${communityLink === 3 ? 'community-links-item-active' : ''}`} onClick={() => setCommunityLink(3)}>Organizers</li>
    </ul>
    {isScrollableRight && <div className="link-container-arrow arrow-right-main" onClick={scrollToEnd}><img src={rightDirection} alt="→" /></div>}
</div>
英文:

I have a React component where I'm displaying a list of items. The list can be scrollable depending on the number of items. I want to display left and right arrow buttons only if the list is scrollable in those directions.

To achieve this, I'm using a useEffect hook that checks if the list is scrollable and sets state variables accordingly. It works, however, when I refresh the page it no longer works, the arrows don't appear even when the list is scrollable. Here's my code:

const [isScrollableLeft, setIsScrollableLeft] = useState(false);
const [isScrollableRight, setIsScrollableRight] = useState(false);
const listRef = useRef();

useEffect(() =&gt; {
    const checkScrollable = () =&gt; {
        if (listRef.current) {
            const { scrollLeft, scrollWidth, clientWidth } = listRef.current;
            setIsScrollableLeft(scrollLeft &gt; 0);
            setIsScrollableRight(scrollWidth &gt; clientWidth + scrollLeft);
        }
    };

    if (listRef.current) {
        listRef.current.addEventListener(&quot;scroll&quot;, checkScrollable);
        // Initial check
        checkScrollable();
    }

    // Clean up the event listener when the component is unmounted
    return () =&gt; {
        if (listRef.current) {
            listRef.current.removeEventListener(&quot;scroll&quot;, checkScrollable);
        }
    };
}, []);

And here's the JSX:

&lt;div className=&quot;community-overall-link-container&quot;&gt;
    {isScrollableLeft &amp;&amp; &lt;div className=&quot;link-container-arrow arrow-left-main&quot; onClick={scrollToStart}&gt;&lt;img src={leftDirection} alt=&quot;←&quot; /&gt;&lt;/div&gt;}
        &lt;ul ref={listRef} className=&quot;community-links-container&quot;&gt;
            &lt;li className={`community-links-item ${communityLink === 1 ? &#39;community-links-item-active&#39; : &#39;&#39;}`} onClick={() =&gt; setCommunityLink(1)}&gt;Upcoming Hangout&lt;/li&gt;
            &lt;li className={`community-links-item ${communityLink === 2 ? &#39;community-links-item-active&#39; : &#39;&#39;}`} onClick={() =&gt; setCommunityLink(2)}&gt;Discussions&lt;/li&gt;
            &lt;li className={`community-links-item ${communityLink === 3 ? &#39;community-links-item-active&#39; : &#39;&#39;}`} onClick={() =&gt; setCommunityLink(3)}&gt;Organizers&lt;/li&gt;
        &lt;/ul&gt;
    {isScrollableRight &amp;&amp; &lt;div className=&quot;link-container-arrow arrow-right-main&quot; onClick={scrollToEnd}&gt;&lt;img src={rightDirection} alt=&quot;→&quot; /&gt;&lt;/div&gt;}
&lt;/div&gt;

答案1

得分: 2

你可以将checkScrollable函数封装在一个单独的函数内,并在组件挂载时通过将函数调用添加到useEffect的依赖数组中来调用它。
如果不使用依赖数组,在页面刷新时,组件可能尚未挂载,初始的useEffect不会被调用。这可能是为什么状态变量isScrollableLeftisScrollableRight没有被设置的原因。

const [isScrollableLeft, setIsScrollableLeft] = useState(false);
const [isScrollableRight, setIsScrollableRight] = useState(false);
const listRef = useRef();

const checkScrollable = () => {
  if (listRef.current) {
    const { scrollLeft, scrollWidth, clientWidth } = listRef.current;
    setIsScrollableLeft(scrollLeft > 0);
    setIsScrollableRight(scrollWidth > clientWidth + scrollLeft);
  }
};

useEffect(() => {
  // 在初始挂载时运行
  checkScrollable();

  if (listRef.current) {
    listRef.current.addEventListener("scroll", checkScrollable);
  }

  // 在卸载时清除事件监听器
  return () => {
    if (listRef.current) {
      listRef.current.removeEventListener("scroll", checkScrollable);
    }
  };
}, [checkScrollable]); // 在挂载时再次调用函数
英文:

You could wrap the checkScrollable function inside a separate function and call it when the component is mounted by adding the function call inside the useEffect dependency array.
Without using the dependency array, when page refreshes the component may not have mounted yet and the initial useEffect doesn't get called. This could be why the state variables isScrollableLeft and isScrollableRight are not getting set.

const [isScrollableLeft, setIsScrollableLeft] = useState(false);
const [isScrollableRight, setIsScrollableRight] = useState(false);
const listRef = useRef();

const checkScrollable = () =&gt; {
  if (listRef.current) {
    const { scrollLeft, scrollWidth, clientWidth } = listRef.current;
    setIsScrollableLeft(scrollLeft &gt; 0);
    setIsScrollableRight(scrollWidth &gt; clientWidth + scrollLeft);
  }
};

useEffect(() =&gt; {
  // Run on initial mount
  checkScrollable();

  if (listRef.current) {
    listRef.current.addEventListener(&quot;scroll&quot;, checkScrollable);
  }

  // Clean up the event listener when unmounted
  return () =&gt; {
    if (listRef.current) {
      listRef.current.removeEventListener(&quot;scroll&quot;, checkScrollable);
    }
  };
}, [checkScrollable]); // Call the function again on mount

huangapple
  • 本文由 发表于 2023年7月17日 23:58:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76706228.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定