首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >setInterval在UseEffect中被呼叫2/4次

setInterval在UseEffect中被呼叫2/4次
EN

Stack Overflow用户
提问于 2022-02-18 07:50:03
回答 1查看 309关注 0票数 0

嗨,我只想点击useEffect一次,但是它被调用了2-3次,我试着用另一个函数包装,但是代码开始刹车,你们能帮忙吗?

需要调用successHandler,但当它被调用时,它会被超过n

代码语言:javascript
复制
  const { successHandler } = props; 
  const [completed, setCompleted] = React.useState(10); 
  const fileType = getFileType(props.fileName); 

  React.useEffect(() => { 
         function progress() { 
            setCompleted(prevCompleted => { 
               if (prevCompleted >= 100) { 
                   successHandler(); 
                   return 100; 
               } 
              return prevCompleted + 10; }); 
         } 
         const timer = setInterval(progress, 500); 
 
         return () => { clearInterval(timer); }; 
      }, [successHandler]); 
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-02-18 07:56:00

如果多次调用useEffect,则意味着依赖项中的某些内容会发生变化。在您的例子中,successHandler会发生变化。看看它是从哪里来的,也许您需要使用useCallback来确保它在重呈现时不会改变。

例如,这将在每次重新呈现时重新运行useEffect,因为f每次都是一个新函数:

代码语言:javascript
复制
const f = () => {};
useEffect(() => { f(); }, [f]);

这将只运行useEffect一次,因为useCallback回传函数,而f不会在每次重呈现时更改:

代码语言:javascript
复制
const f = useCallback(() => {}, []);
useEffect(() => { f(); }, [f]);

稍后编辑-我想这个问题。试着像这样重写它:

代码语言:javascript
复制
const { successHandler } = props;
const [completed, setCompleted] = React.useState(10);
const fileType = getFileType(props.fileName);

React.useEffect(() => {
  function progress() {
    setCompleted(prevCompleted => Math.max(100, prevCompleted + 10));
  }
  const timer = setInterval(progress, 500);
  return () => {
    clearInterval(timer);
  };
}, []);

React.useEffect(() => {
  if (completed === 100) {
    successHandler();
  }
}, [completed, successHandler]);

这样,successHandler只应该在完成变成100时才调用一次(考虑到successHandler不会改变)。

您可能也希望停止进度为100的时间,因此您可以这样做:

代码语言:javascript
复制
const { successHandler } = props;
const [completed, setCompleted] = React.useState(10);
const fileType = getFileType(props.fileName);
const timer = React.useRef(null);

const stopTimer = React.useCallback(() => {
  if (timer.current) {
    clearInterval(timer.current);
    timer.current = null;
  }
}, []);

React.useEffect(() => {
  function progress() {
    setCompleted(prevCompleted => Math.max(100, prevCompleted + 10));
  }
  timer.current = setInterval(progress, 500);
  return stopTimer;
}, [stopTimer]);

React.useEffect(() => {
  if (completed === 100) {
    stopTimer();
    successHandler();
  }
}, [completed, stopTimer, successHandler]);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71169998

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档