react hooks 事件监听

说明

dom监听事件的绑定和解绑只执行一次。在react hooks中实现,需要使用useEffect。

useEffect

简单了解下useEffect是做什么的?React 组件在渲染后执行某些操作( DOM 更新之后调用useEffect的第一个参数函数),还有默认情况下,它在第一次渲染之后和每次更新之后都会执行。

useEffect执行一次

useEffect第二个参数传入空的依赖数组 [],意味着该 hook 只在组件挂载时运行一次,并非重新渲染时。

useEffect绑定和解绑事件

简单以setInterval为例

   useEffect(() => {
    const id = setInterval(() => {}, 1000);
    return () => clearInterval(id);
  },[]);

问题:变量和state值不变且是初始值

但如此会有问题,在useEffect第一参数函数内,一般变量和state的值不会发生变化。因为当 effect 执行时,会创建一个闭包,并将 一般变量和state的值被保存在该闭包当中,且为初始值。

监听事件

下面以Orientation(横竖屏依赖模块)为例简单记录下解决方法
需求:监听横竖屏切换,触发事件拿到当前tabsIndex

起初,问题代码

 const [tabsIndex, setTabsIndex] = useState(2);		
 //	setTabsIndex()改变tabsIndex
 useEffect(()=>{
   const targetFn=()=>{
     setTimeout(()=>{
       scrollViewRef.current.scrollTo({ x: tabsIndex*width, animated: false });
     },0);
   }
   Orientation.addOrientationListener(targetFn);
   return () => Orientation.removeOrientationListener(targetFn);
 },[]);

上面说过原因,targetFn中的tabsIndex一直是初始值2,不变。横竖屏切换时监听事件是触发了,但是内部tabsIndex值不正确,造成了无法滚动到指定位置。

解决方法1

/**组件外定义**/
const useOrientationListener=()=>{
  const [triggerN,setTriggerN]=useState(0);
  useEffect(()=>{
    const targetFn=()=>setTriggerN(n=>n+1);
    Orientation.addOrientationListener(targetFn);
    return () => Orientation.removeOrientationListener(targetFn);
  },[]);
  return triggerN;
}
/**组件内使用**/
const [tabsIndex, setTabsIndex] = useState(2);
//	setTabsIndex()改变tabsIndex
const oriN=useOrientationListener();
 useEffect(() => { 
     setTimeout(() => {
       scrollViewRef.current.scrollTo({ x: tabsIndex*width, animated: false });
     }, 0)
 }, [oriN]);

useOrientationListener内useEffect [] 保证了只监听一次事件,触发时,将触发次数这个state传递给组件的useEffect,useEffect会依赖oriN的变化而执行第一参数函数体

解决方法2

/**组件内部**/
const tabsIndex = useRef(2);
//tabsIndex.current 赋值
useEffect(()=>{
  const targetFn=()=>{
    setTimeout(()=>{
      scrollViewRef.current.scrollTo({ x: tabsIndex.current *width, animated: false });
    },0);
  }
  Orientation.addOrientationListener(targetFn);
  return () => Orientation.removeOrientationListener(targetFn);
},[]);

利用了useRef的特性规避了内部state是初始值的问题,下面是部分知识点

  1. useRef 就像是可以在其 .current 属性中保存一个可变值的“盒子”
  2. useRef 会在每次渲染时返回同一个 ref 对象
  3. 当 ref 对象内容发生变化时,useRef 并不会通知你
  4. 变更 .current 属性不会引发组件重新渲染
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值