如何正确使用useEffect()?

时间:2020-04-03 11:43:30

标签: javascript reactjs graphql react-hooks

我想通过滚动更改样式。

此代码无法正常工作 。 当我上下滚动太多次且速度太快时,浏览器将冻结,崩溃。

我认为我用错了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要么没有依赖项数组,要么在每个渲染器上都有一个依赖项更改。

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

2 个答案:

答案 0 :(得分:3)

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

尝试以下操作:

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

我希望这会有所帮助!

答案 1 :(得分:0)

好吧,问题始终在您可以使用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是正确的