怎么做照片网站,zhi做网站,邯郸营销网站建设公司,做网站赚多少在 react 开发中#xff0c; useEffect 是我们经常会使用到的钩子#xff0c;一个基础的例子如下#xff1a; 
useEffect(()  {// some code here// cleanup 函数return ()  {doSomething()}
}, [dependencies])上述代码中#xff0c; cleanup 函数的执行时机有如下…在 react 开发中 useEffect 是我们经常会使用到的钩子一个基础的例子如下 
useEffect(()  {// some code here// cleanup 函数return ()  {doSomething()}
}, [dependencies])上述代码中 cleanup 函数的执行时机有如下两种 
组件卸载时会执行一次每个依赖项dependencies变更后页面重新渲染前会执行一次 
在日常的开发中我们很多人都会忽略掉 cleanup 函数在一般情况下不写 cleanup 函数不会有什么问题。但如果我们在 useEffect中使用了定时器或者进行了网络请求这种情况下如果不在 cleanup 函数中执行一些清除逻辑会导致一些潜在的 bug。下面来聊聊如何使用 cleanup 函数解决内存占用和网络请求竞态问题. 
不在 cleanup 函数中清除旧定时器会发生什么 
我们使用 interval 写一个计数器例子count 从 0 开始每秒递增 1如下 
function Counter() {let [count, setCount]  useState(0)useEffect(()  {console.log(effect)setInterval(()  {setCount(count  1)}, 1000)}, [count])return (divdiv{count}/div/div)
} 
上述例子一开始递增到前面几个数字页面看起来是正常的但是越往后就会发现数字在闪烁而且之后页面会卡住一段时间后的结果如下  上图中count 递增到 15 但 useEffect 却运行了 95 次也就是此时页面上已经有了 95 个定时器越往后定时器越多为什么会这样正常的结果应该是 count 增加到多少 useEffect 就运行多少次 (除了初始渲染运行的那一次)因为我们把 count 作为 useEffect 的依赖项。 
导致上述问题的根本原因是我们没有清除旧的定时器count 发生变化时组件会重新渲染 useEffect 重新运行会创建一个新的定时器而旧的定时器并没有被清除导致多个定时器同时存在占用了更多的内存这就是后续页面卡住的原因。 
而页面上的数字闪烁的问题是因为每次组件重新渲染时都会重新调用 useEffect导致新的定时器开始运行而旧的定时器还在继续工作。这样就会出现两个定时器交替执行的情况导致数字的变化不稳定造成闪烁的效果。 
解决办法就是在 cleanup 函数中清除旧的定时器代码如下 
function Counter() {// ...useEffect(()  {console.log(effect)const interval  setInterval(()  {setCount(count  1)}, 1000)return ()  {clearInterval(interval)}}, [count])// ...
}清除旧的定时器之后页面的表现就符合预期了每次重新渲染页面上有且只有一个定时器。 
除了定时器这种场景其他场景如订阅、使用 IntersectionObserver 观察者都需要注意在 cleanup 函数中执行对应的清除逻辑以避免内存泄露问题。 
cleanup 函数解决网络请求问题 
case1离开页面时请求未完成 
一个在 useEffect 中进行网络请求例子如下 
function List() {const [lists,setLists]  useState([])useEffect(()  {fetch(https://jsonplaceholder.typicode.com/todos).then(res  res.json()).then(data  {alert(请求完成)setLists(data)})}, [])return (div{lists?.map((item)  (p key{item.id}{item.title}/p))}/div)
}export default List上述代码是一个列表组件通过 fetch 请求获取列表数据最终渲染在页面上这看起来没什么问题我们平常就是这么写的。 
我们增加一个 Home 组件功能很简单就是从 Home 页面跳转到上述的 List 页面代码如下 
import { Link } from react-router-domfunction Home() {return (divLink to/listGo to lists/Link/div)
}export default Home我们从 Home 页面跳转到 List 页面然后 List 页面开始请求 list 列表数据。跳到 List 页面后在请求完成之前通过浏览器的回退按钮回到 Home 页面交互过程如下 浏览器后退按钮取消请求 视频中我们把网络设置成弱网环境在 List 页面的 fetch 请求还没完成就回到了 Home 页面我们期望 then 回调里的代码不应该执行因为离开了 List 页面后List 组件相当于销毁了不应该再继续执行组件代码然而结果却是执行了。 
造成上述结果的原因是fetch 请求是异步的进入 List 页面请时求已经发出离开 List 页面没有取消请求所以请求继续进行完成后就会执行 then 回调里的代码。 
解决办法如下 
// ...
useEffect(()  {let isCancelled  falsefetch(https://jsonplaceholder.typicode.com/todos).then(res  res.json()).then(data  {if (!isCancelled) {alert(请求已完成)setLists(data)}})return ()  {isCancelled  true}
}, [])
// ...上述代码中我们定义了一个标志位变量isCancelled表示当前请求是否需要取消这里并不是真正的取消请求如何取消请求下文会讲到初始化为 false在 then 回调里只有判断请求不需要取消才会执行后续代码。最后重点来了前面讲到 cleanup 函数的执行时机之一是在组件销毁时所以在离开 List 页面时我们把 isCancelled 设置为 true那么后续请求完成时就不会进入 if (!isCancelled) {} 条件语句中。 
case2同时触发多个相同请求网络竞态问题 
定义一个 User 组件如下 
import { useState, useEffect } from react;
import {useLocation,Link} from react-router-domfunction User() {const [curUser,setCurUser]  useState({})const route  useLocation()const id  route.pathname.split(/)[2]useEffect(()  {fetch(https://jsonplaceholder.typicode.com/users/${id}).then(res  res.json()).then(data  {setCurUser(data)})}, [id])return (div style{{display: flex,flexDirection: column,alignItems: center}}pname: {curUser.name}/ppusername: {curUser.username}/ppemail: {curUser.email}/pLink to/users/1fetch user 1/LinkLink to/users/2fetch user 2/LinkLink to/users/3fetch user 3/Link/div)
}export default User上述是一个获取用户信息并展示在页面上的例子我们点击 Link 组件更新路由中的用户 id在 useEffect 中根据 id 去请求用户数据。在网络正常的情况下我们快速切换用户 id页面上的用户信息就会跟着改变这看起来没什么问题。如果我们把网络设置成弱网环境同样的操作结果如下 网络请求竞态视频1 在上述视频中当前用户是 user1我们快速点击 fetch user2、fetch user3并最终停留在 user3正常情况下最终页面展示的应该是 user3 的信息但是实际结果是先展示 user2 的信息然后再展示 user3 的信息。 
上述问题其实涉及到了网络竞态问题。网络竞态是用户触发同一个请求多次由于网络的波动每个请求的响应时间是不一样的最先触发的请求可能是最后一个返回响应的最后触发的请求也可能是最先返回响应的最终所有请求完成后我们应该使用哪个请求的响应作为最终的数据结果。答案使用最后一个触发的请求的响应作为最终的结果因为这是最新的最具时效性的数据。 
在上述 fetch user 的例子中我们应该丢弃 fetch user2 的响应因为我们最后操作的是 fetch user 3页面最终应该展示的是 user3 的数据。我们同样使用 cleanup 函数来解决网络竞态问题写法和 case1 类似如下 
// ...
useEffect(()  {let isCancelled  falsefetch(https://jsonplaceholder.typicode.com/users/${id}).then(res  res.json()).then(data  {if (!isCancelled) {setCurUser(data)}})return ()  {isCancelled  true}}, [id])
// ...前面讲到 cleanup 函数的另一个执行时机是每个依赖项变更后页面重新渲染前运行一次所以我们快速点击 fetch user2、fetch user3id 从 2 到 3那么id 为 2 时对应的 isCancelled 变量被设置为了 true所以此时就不会进入 if (!isCancelled) {} 条件语句中执行 setCurUser(data)那么 id 为 2 的这条响应就被丢弃了最终页面就不会先展示 user2 的信息再展示 user3 的信息。最终结果视频所示 网络请求竞态视频2 拓展 
前面我们讲了如何借助 cleanup  函数来丢弃响应但可能很多时候对于无效的请求我们希望能取消它对于 fetch 请求我们借助 fetch 的第二个参数中 signal 和 AbortController 实现如下 
// ...
useEffect(()  {let controller  new AbortController()let signal  controller.signalfetch(https://jsonplaceholder.typicode.com/users/${id},{signal}).then(res  res.json()).then(data  {setCurUser(data)})return ()  {// 在 cleanup 函数中终止当前请求controller.abort()}
}, [id])// ...结果如下 取消网络请求 在上述视频中我们看到在点击 fetch user3 之后fetch user2 的请求状态变成了已取消。 
在平时的开发中我们一般会用 axios 进行请求下面是 axios 取消请求的例子 
import axios from axios
// ...
useEffect(()  {const CancelToken  axios.CancelTokenconst source  CancelToken.source()axios.get(https://jsonplaceholder.typicode.com/users/${id},{cancelToken: source.token}).then(res  {setCurUser(res.data)})return ()  {source.cancel()}
}, [id])// ...
 文章转载自: http://www.morning.rswfj.cn.gov.cn.rswfj.cn http://www.morning.spwln.cn.gov.cn.spwln.cn http://www.morning.smj79.cn.gov.cn.smj79.cn http://www.morning.rnmyw.cn.gov.cn.rnmyw.cn http://www.morning.rcqyk.cn.gov.cn.rcqyk.cn http://www.morning.wdykx.cn.gov.cn.wdykx.cn http://www.morning.dysgr.cn.gov.cn.dysgr.cn http://www.morning.ftntr.cn.gov.cn.ftntr.cn http://www.morning.kfrhh.cn.gov.cn.kfrhh.cn http://www.morning.tnnfy.cn.gov.cn.tnnfy.cn http://www.morning.rrwft.cn.gov.cn.rrwft.cn http://www.morning.khpgd.cn.gov.cn.khpgd.cn http://www.morning.wncb.cn.gov.cn.wncb.cn http://www.morning.qsmch.cn.gov.cn.qsmch.cn http://www.morning.nynpf.cn.gov.cn.nynpf.cn http://www.morning.tqdlk.cn.gov.cn.tqdlk.cn http://www.morning.nflpk.cn.gov.cn.nflpk.cn http://www.morning.zdxss.cn.gov.cn.zdxss.cn http://www.morning.wynqg.cn.gov.cn.wynqg.cn http://www.morning.prprz.cn.gov.cn.prprz.cn http://www.morning.kspfq.cn.gov.cn.kspfq.cn http://www.morning.yhljc.cn.gov.cn.yhljc.cn http://www.morning.burpgr.cn.gov.cn.burpgr.cn http://www.morning.zlzpz.cn.gov.cn.zlzpz.cn http://www.morning.htrzp.cn.gov.cn.htrzp.cn http://www.morning.pcjw.cn.gov.cn.pcjw.cn http://www.morning.nwpnj.cn.gov.cn.nwpnj.cn http://www.morning.pznnt.cn.gov.cn.pznnt.cn http://www.morning.mnkhk.cn.gov.cn.mnkhk.cn http://www.morning.yjqkk.cn.gov.cn.yjqkk.cn http://www.morning.ryrgx.cn.gov.cn.ryrgx.cn http://www.morning.khdw.cn.gov.cn.khdw.cn http://www.morning.pnfwd.cn.gov.cn.pnfwd.cn http://www.morning.rbmm.cn.gov.cn.rbmm.cn http://www.morning.sjftk.cn.gov.cn.sjftk.cn http://www.morning.tpqrc.cn.gov.cn.tpqrc.cn http://www.morning.jpkhn.cn.gov.cn.jpkhn.cn http://www.morning.kgxrq.cn.gov.cn.kgxrq.cn http://www.morning.rqmr.cn.gov.cn.rqmr.cn http://www.morning.wcczg.cn.gov.cn.wcczg.cn http://www.morning.xdttq.cn.gov.cn.xdttq.cn http://www.morning.deanzhu.com.gov.cn.deanzhu.com http://www.morning.wnkqt.cn.gov.cn.wnkqt.cn http://www.morning.sjbpg.cn.gov.cn.sjbpg.cn http://www.morning.ksgjn.cn.gov.cn.ksgjn.cn http://www.morning.jkwwm.cn.gov.cn.jkwwm.cn http://www.morning.lswgs.cn.gov.cn.lswgs.cn http://www.morning.drbwh.cn.gov.cn.drbwh.cn http://www.morning.tztgq.cn.gov.cn.tztgq.cn http://www.morning.sqmbb.cn.gov.cn.sqmbb.cn http://www.morning.fktlg.cn.gov.cn.fktlg.cn http://www.morning.mfsjn.cn.gov.cn.mfsjn.cn http://www.morning.pphbn.cn.gov.cn.pphbn.cn http://www.morning.tjmfz.cn.gov.cn.tjmfz.cn http://www.morning.ftwlay.cn.gov.cn.ftwlay.cn http://www.morning.mnbcj.cn.gov.cn.mnbcj.cn http://www.morning.yzxlkj.com.gov.cn.yzxlkj.com http://www.morning.xlndf.cn.gov.cn.xlndf.cn http://www.morning.cpfbg.cn.gov.cn.cpfbg.cn http://www.morning.kzdwt.cn.gov.cn.kzdwt.cn http://www.morning.fwblh.cn.gov.cn.fwblh.cn http://www.morning.qyrnp.cn.gov.cn.qyrnp.cn http://www.morning.lsfbb.cn.gov.cn.lsfbb.cn http://www.morning.rnlx.cn.gov.cn.rnlx.cn http://www.morning.pxdgy.cn.gov.cn.pxdgy.cn http://www.morning.jklns.cn.gov.cn.jklns.cn http://www.morning.ssglh.cn.gov.cn.ssglh.cn http://www.morning.ypjjh.cn.gov.cn.ypjjh.cn http://www.morning.rbgwj.cn.gov.cn.rbgwj.cn http://www.morning.rrgm.cn.gov.cn.rrgm.cn http://www.morning.yrpg.cn.gov.cn.yrpg.cn http://www.morning.dkqyg.cn.gov.cn.dkqyg.cn http://www.morning.jmdpp.cn.gov.cn.jmdpp.cn http://www.morning.sjbpg.cn.gov.cn.sjbpg.cn http://www.morning.hdscx.cn.gov.cn.hdscx.cn http://www.morning.nrbcx.cn.gov.cn.nrbcx.cn http://www.morning.pcwzb.cn.gov.cn.pcwzb.cn http://www.morning.cttgj.cn.gov.cn.cttgj.cn http://www.morning.gcszn.cn.gov.cn.gcszn.cn http://www.morning.rfpxq.cn.gov.cn.rfpxq.cn