当前位置: 首页 > Web前端 > HTML

明白为什么要为useEffect声明依赖

时间:2023-03-28 18:34:07 HTML

在使用useEffect、useCallback等hook时,为什么要写依赖数组?如果你不写这些依赖,React会给你一个警告。下面分享一下我对声明依赖目的的理解:防止函数的闭包特性导致的意外错误。目的是想让它每1秒跳转到下一盏灯。Red=>Green=>Yellow=>Red=>Green=>Yellow但是我发现下面这串代码只有绿灯和黄灯亮。importReact,{useState,useEffect}from"react";importclassesfrom"./TrafficLight.module.css";importLightfrom"./Light";letcurIdex=0;constTrafficLight=()=>{const[灯,setLights]=useState([{on:true,color:"red",id:0},{on:false,color:"green",id:1},{on:false,color:"yellow",id:2},]);console.log('当前灯:',灯);useEffect(()=>{letcurIdex=0;consttimer=setInterval(()=>{curIdex+=1;if(curIdex>=lights.length)curIdex=0;console.log('receivedlights',lights)toggleLight(lights[curIdex]);},1000*1);},[]);返回()=>清除超时(计时器);},[灯]);consttoggleLight=(curLight)=>{setLights(lights.map((light)=>light===curLight?{...light,on:!light.on}:{...light,on:false}));};常量htList=lights.map((light)=>{return;});return{lightList}

;};exportdefaultTrafficLight;//----------------分割线----------------从“react”导入React;从“./Light.module.css”导入类;constLight=({light,onToggle})=>{return(onToggle(light)}/>);};导出默认光;打开控制面板看,发现每次调用toggleLight时,获取的灯还是初始状态。TrafficLight组件的灯虽然更新了,但是toggleLight函数获取的灯并没有更新,所以每次toggleLight都不会点亮红灯关闭的原因:useEffect依赖空数组,只会在第一次渲染时被调用。TrafficLight组件的第一次渲染:调用useEffect并声明其回调函数:useEffect(()=>{letcurIdex=0;consttimer=setInterval(()=>{curIdex+=1;if(curIdex>=lights.length)curIdex=0;toggleLight(lights[curIdex]);},1000*1);},[]);这个时候这个回调函数获取到的灯就是我们预设的灯。TrafficLight组件函数执行后,函数生成的执行上下文从栈中移除。但是setInterval的回调函数会在1秒后执行,更新组件状态,组件开始第二次渲染。TrafficLight组件的二次渲染:此时灯已经更新了,红灯的on变成了false。但是useEffect不会再被调用,因为它的依赖是一个空数组。这样一来,useEffect的回调函数就不会被重新定义,setInteval依然会调用第一次渲染时定义的回调函数。由于函数的词法作用域,该函数一直无法获取更新的数据。为了避免这种情况,我们需要添加一个依赖数组。总结一下dependency,dependency,顾名思义,useEffect回调函数的正常运行有时会依赖于一些外部变量。如果这些变量发生变化,回调函数获取的变量不会同步更新。只有重新定义这个回调函数才能得到更新后的变量。重新定义它的回调函数相当于再次调用useEffect。useCallback也是同样的道理css代码.container{height:20rem;宽度:7rem;背景色:#2c3e50;边界半径:3.5rem;填充:0.7rem0;显示:弹性;弹性方向:列;证明内容:周围空间;对齐项目:居中;位置:固定;顶部:1rem;右:2rem;}.light{宽度:4rem;高度:4rem;边界半径:50%;背景颜色:rgba(0,0,0,0.35);显示:弹性;证明内容:flex-start;对齐项目:居中;}.light::after{内容:“”;显示:块;宽度:80%;高度:80%;边界半径:50%;border-right:4pxsolidrgba(255,255,255,0.6);}.light.red{background-color:#c0392b;box-shadow:0020px5px#c0392b;}.light.yellow{背景色:#f1c40f;box-shadow:0020px5px#f1c40f;}.light.green{背景色:#2ecc71;盒子阴影:0020px5px#2ecc71;}