【问题标题】:How to use useEffect() correctly?如何正确使用 useEffect()?
【发布时间】:2020-07-15 13:52:51
【问题描述】:

我想通过滚动来改变样式。

此代码无法正常工作 . 当我上下滚动太多次太快时,浏览器就会死机、崩溃。

我想我用错了useEffect()。我该如何解决这个问题。

const ArticleItem = ({title, content, active, chapter, program, id, scrollPos}) => {
  const ref = useRef(null);
  const client = useApolloClient();

  useEffect(() => {
    if(ref.current.offsetTop <= (scrollPos + 200)) {
      client.writeData({data: {
        curChapter: chapter.num,
        curArticle: id,
        curProgram: program.name
      }});
    }
  });

  if(active === false)
    return ( // Inactive Article
      <div className='section-item' ref={ref}>
        <h2>{title.toUpperCase()}</h2>
        <ReactMarkdown source={content} />
        <br />
      </div>
    )
  return (  // Active Article
    <div className='section-item active' ref={ref}>
      <h2>{title.toUpperCase()}</h2>
      <ReactMarkdown source={content} />
      <br />
    </div>
  )
}

结果,我遇到了这个警告。

警告:已超出最大更新深度。当组件在 useEffect 中调用 setState 时,可能会发生这种情况,但 useEffect 要么没有依赖数组,要么每次渲染时其中一个依赖项都发生了变化。

我认为这是问题的原因?!

【问题讨论】:

  • 您还需要包含 useEffect 的依赖数组。这样它就无限运行了。可能您想在其中包含scrollPos
  • @norbitrial 是正确的,请执行:useEffect(() =&gt; {}, [dependency] 现在该函数仅在依赖值更改时才会运行。您可能还想谴责,这意味着只有在一定时间内没有改变时才更新
  • @Elias 认为你的意思是“去抖动”
  • 哦,是的......对不起

标签: javascript reactjs graphql react-hooks


【解决方案1】:

根据我上面的评论,您还需要包含 useEffect 的依赖数组。以目前的方式,它无限运行。可能您想将scrollPos 包含在其中,因此它只会在scrollPos 发生变化时触发。

尝试以下方法:

useEffect(() => {
    if(ref.current.offsetTop <= (scrollPos + 200)) {
      client.writeData({data: {
        curChapter: chapter.num,
        curArticle: id,
        curProgram: program.name
      }});
    }
}, [scrollPos]);

我希望这会有所帮助!

【讨论】:

【解决方案2】:

好吧,问题一直被触发,您可以使用scroll 事件监听器并在触发此事件时进行更改。

const [scrollItem, setScrollItem] = useState(null);

const handleScroll() {
  if(scrollItem) {
     // logic goes here
  }
}

useEffect(() => {
  window.addEventListener('scroll', handleScroll);

  return () => {
    window.removeEventListener('scroll', handleScroll);
  };
}, []); // initialize event only once

return (
   <div ref={setScrollItem}>
      ...
   </div>
);

编辑

避免那个解决方案,@norbitrial 是对的

【讨论】:

  • 好吧,你正在为scroll 添加一个事件监听器,他似乎是从道具中接收到的。
  • 嗯,确实,我没看到。
  • 嗯,事情是……这实际上性能更高,但不是他要求的……每次有人滚动时渲染组件可能效率很低
猜你喜欢
  • 2021-08-05
  • 2020-11-29
  • 1970-01-01
  • 2022-07-16
  • 2021-11-16
  • 2020-03-01
  • 2020-09-15
  • 2021-01-24
  • 2020-09-25
相关资源
最近更新 更多