经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » React » 查看文章
react中useRef的应用
来源:cnblogs  作者:mikumikugo  时间:2023/5/26 9:54:45  对本文有异议

何为useRef

useRef是随着react函数式组件发展而来的,是react众多官方hook中的一个,调用useRef可以返回一个伴随这组件整个声明周期不发生改变的对象,这个对象常见的用途有两个:

  • 用于绑定dom元素,从而实现对dom元素的操作
  • 用于保存不希望随着组件重新渲染而改变的值,如定时器

在项目中的应用

我在做自己的网站时遇到过一些场景,实现效果与预想中的不一致,让我头大了好一阵子,所幸最终都得到了解决,为了在以后能够回来看一下,同时记录学习过程中的一些知识点,现将这两个场景记录如下。

一、编写自己的防抖函数

在编写登录注册功能时,需要对用户输入的信息进行校验,包括前端的校验以及和后端通信的校验,如果只是前端的校验还好,如果在用户输入的信息每次发生变化都去和服务器通信校验的话,大量的http请求会对服务器造成压力,所以我希望对这些行为进行防抖处理。

useDebounce.ts

  1. import { useEffect, useRef } from "react"
  2. export const useDebounce = (f:Function,delay:number)=>{
  3. //使用useRef保存计时器,以此确保在组件更新时始终是同一个计时器,而不是重新创建
  4. const {current} = useRef<{timmer:any}>({timmer:null})
  5. useEffect(()=>{
  6. return ()=>{
  7. //组件销毁时清除计时器
  8. clearTimeout(current.timmer)
  9. }
  10. },[])
  11. return function(...args:any[]){
  12. //如果计时器存在,则清除该计时器
  13. if(current.timmer){
  14. clearTimeout(current.timmer)
  15. }
  16. //重新赋值计时器,并在计时结束后执行回调函数
  17. current.timmer = setTimeout(() => {
  18. f.apply(useDebounce,args)
  19. }, delay);
  20. }
  21. }

这里我将防抖函数写成了一个自定义的hook,也是写的第一个hook,调用时需要传入两个参数,第一个参数是需要进行防抖处理的函数,第二个参数是防抖的延时时间,hook返回值是经过防抖处理的函数。

二、解决回调函数中获取不到最新state值的问题

在实现获取评论列表时,我希望每次只获取一定数量的评论,当用户浏览到页面底端时再获取新的评论,在实现过程中我用到了intersectionObserverAPI,并在它的回调函数中引用了组件中的一些state。

当我直接在useEffect副作用函数中进行绑定监听的元素时,发现回调函数中的state值一直保持observer对象创建时的值,经过查询相关资料,得知这可能是因为闭包的影响。解决办法是使用useRef创建一个对象用于保存observer对象,并在相关state值发生变化后释放原来的observer对象,创建一个新的observer对象,并重新绑定要监听的元素。

  1. //指向要监听的元素
  2. const bref = useRef(null)
  3. //保存observer对象
  4. const observer = useRef<any>()
  5. //每当comments变化,都会重新创建一个observer对象,其回调函数中引用的就是最新的state值
  6. useEffect(() => {
  7. let c = new IntersectionObserver((entries) => {
  8. if (entries[0].intersectionRatio > 0) {
  9. if (page * pageNum <= count) {
  10. const fd = new FormData()
  11. fd.append('articleId', param.articleid)
  12. fd.append('page', page + 1)
  13. fd.append('pageNum', pageNum)
  14. http({ url: '/comment/comments', options: { method: 'POST', body: fd } }).then(res => {
  15. if (count !== res.count) {
  16. setcount(res.res.count)
  17. }
  18. setpage(page + 1)
  19. setcomments([...comments, ...res.res.rows])
  20. })
  21. }
  22. }
  23. })
  24. //取消旧的监听
  25. if (observer.current) {
  26. observer.current.unobserve(bref.current)
  27. }
  28. //保存新的observer对象,并建立新的监听
  29. observer.current = c
  30. observer.current.observe(bref.current)
  31. }, [comments])



实践出真知,在项目中发现问题,寻找解决问题的方法,大江不止兮水长流,不断积累,丰富阅历,提升能力。

原文链接:https://www.cnblogs.com/oumannrinn/p/17432807.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号