1. 首页

React16.7 hooks之setTimeout引发的bug小记

前言

  周末尝试了一下React新的hooks功能,来封装一个组件,遇到一个bug,所以记录一下过程!

报错如下:

Warning: Can’t perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.in Notification

大概意思是组件已经卸载了,但在卸载之后还执行了一个对组件更新的操作,这是一个无效的操作,但它表示应用程序中存在内存泄漏。要修复,请取消useEffect cleanup function.in Notification 中的所有订阅和异步任务
Can't perform a React state update on an unmounted component.,Read the Motivation to learn why we’re introducing Hooks to React,首席填坑官∙苏南的专栏,梅斌的专栏,webpack4,webpack:从入门到真实项目配置,react组件封装,Hooks are a new feature proposal that lets you use state and other React features without writing a class. They’re currently in React v16.7.0-alpha and being discussed in an open RFC

组件核心代码如下:


function Notification(props){ var timer = null; const [visible, setVisible] = useState(false); let {title,description,duration,theme,onClose,}= props; let leave = (source='') => { clearTimeout(timer); setVisible(false); console.log("注意这里是 leave方法里,timer的id:"+timer,"事件的来源:",source); console.log("leave result:",timer); onClose&&onClose(); } let enter = () => { setVisible(true); if( duration > 0 ){ let timer = setTimeout(() => { console.log(`auto carried out`,timer) //timer Number Id leave(`Time to`); }, duration*1000); console.log(`enter方法里,timer的id:`,timer) //timer Number Id } } useEffect(()=>{ enter(); },[]) return ( <div className={`${prefixCls}-notice`} style=display:`${visible?'':'none'}`> {!!theme&&<p className={`${prefixCls}-notice-icon`}><Svg iconId={`svg-${theme}`} /></p>} <div className={`${prefixCls}-notice-content`}> ……//首席填坑官∙苏南的专栏 交流:912594095、公众号:honeyBadger8 </div> <p className={`${prefixCls}-notice-colse`} title="关闭" onClick={()=>leave("手动点击的关闭")}><Svg/></p> </div> ); }; //Hooks" - What to Expect,Read the Motivation to learn why we’re introducing Hooks to React.

简单分析:

  • 首先useEffect方法,是react新增的,它是componentDidMountcomponentDidUpdatecomponentWillUnmount三个生命周期的合集,
  • 也就是之前的写法,上面三生命周期里会执行到的操作,useEffect都会去做;
enter、leave方法
  • 很好理解,进场出场两函数,
  • 进场:加了个定时器,在N秒后执行出场即leave方法,这个逻辑是正常的,
  • 问题就出在手动执行leave,也就是onclick事件上,
问题原因:
  • 其实就是在点击事件的时候,没有获取到 timer的id,导致了定时器没有清除掉;
    !!看图说话:

React v16.7 "Hooks" - What to Expect -点击累加的计数器,公众号:honeyBadger8,Hooks API Reference – React,Here, useState is a Hook we’ll talk about what this means in a moment. We call it inside a function component to add some local state to it. React will preserve this state between re-renders. useState returns a pair: the current state value and a function that lets you update it. You can call this function from an event handler or somewhere else. It’s similar to this.setState in a class

解决思路:
  • 当然是看官方文档,hooks对我来说也是个新玩意,不会~
  • 1、useEffect方法里return 一个方法,它是可以在组件卸载时执行的,
  • 2、清除定时器它有自己的方式,const intervalRef = useRef();指定赋值后能同步更新,之前的timer手动执行没有拿到timer所以没有清除掉;

React v16.7 "Hooks" - What to Expect - 知乎,点击累加的计数器,公众号:honeyBadger8

参考链接:

英文的没有找到
英文的也补一下吧
github也有人提到这个问题,学习了

完美解决:

点击累加的计数器,公众号:honeyBadger8


function Notification(props){ var timer = null; const [visible, setVisible] = useState(false); let {title,description,duration,theme,onClose,}= props; const intervalRef = useRef(null); let leave = (source='') => { clearTimeout(intervalRef.current); setVisible(false); console.log("leave result:",source,intervalRef); onClose&&onClose(); } let enter = () => { setVisible(true); if( duration > 0 ){ let id = setTimeout(() => { console.log(`auto carried out`,intervalRef) //timer Number Id leave(`Time to`); }, duration*1000);//首席填坑官∙苏南的专栏 交流:912594095、公众号:honeyBadger8 intervalRef.current = id; } } useEffect(()=>{ enter(); return ()=>clearTimeout(intervalRef.current); },[]) return ( <div className={`${prefixCls}-notice`} style=display:`${visible?'':'none'}`> {!!theme&&<p className={`${prefixCls}-notice-icon`}><Svg iconId={`svg-${theme}`} /></p>} <div className={`${prefixCls}-notice-content`}> ……//首席填坑官∙苏南的专栏 交流:912594095、公众号:honeyBadger8 </div> <p className={`${prefixCls}-notice-colse`} title="关闭" onClick={()=>leave("手动点击的关闭")}><Svg/></p> </div> ); }; //react.docschina,苏南的专栏

看完两件小事

如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:

  1. 关注我们的 GitHub 博客,让我们成为长期关系
  2. 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
  3. 关注公众号 「画漫画的程序员」,公众号后台回复「资源」 免费领取我精心整理的前端进阶资源教程

JS中文网是中国领先的新一代开发者社区和专业的技术媒体,一个帮助开发者成长的社区,目前已经覆盖和服务了超过 300 万开发者,你每天都可以在这里找到技术世界的头条内容。欢迎热爱技术的你一起加入交流与学习,JS中文网的使命是帮助开发者用代码改变世界

本文著作权归作者所有,如若转载,请注明出处

转载请注明:文章转载自「 Js中文网 · 前端进阶资源教程 」https://www.javascriptc.com

标题:React16.7 hooks之setTimeout引发的bug小记

链接:https://www.javascriptc.com/166.html

« 浅谈react 那些事~
【 ECMAScript 6进阶二十】之ES6 完全使用手册»
Flutter 中文教程资源

相关推荐

QR code