Adinnet-Web Adinnet-Web
首页
  • 技术沉淀

    • 技术沉淀
  • 前端文章

    • JavaScript
  • 前端笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 实用技巧
收藏
  • 分类
  • 标签
  • 归档
首页
  • 技术沉淀

    • 技术沉淀
  • 前端文章

    • JavaScript
  • 前端笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 实用技巧
收藏
  • 分类
  • 标签
  • 归档
  • JavaScript文章

  • 学习笔记

  • 技术沉淀

    • CSS矩形绘制
    • 仿微信通讯录
    • 微信小程序订阅消息
    • 保存海报
    • 微信小程序页面弹框
    • 微信小程序在指定距离范围内签到
    • h5嵌套u3d,使用iframe进行交互
    • 前端主导文件处理方法
    • 图片压缩方法封装
    • 金额大写函数
    • 前端主导的小程序一键导航功能
    • uniapp富文本组件(只支持H5)
    • uniapp二次确认弹框组件(依赖于uview)
    • 无缝滚动插件(vue3)
    • H5与unity通信(只针对unity嵌套H5)
    • 辅助触控
    • 关系图
    • h5&svg点赞动效
    • iframe高精地图文件预览
    • 自适应横向瀑布流布局
    • 考试功能
    • 仿小说翻页
    • 富文本
    • h5唤醒App
    • vue3 Count-to数字翻动
    • 小程序图片转base64
    • 第三方应用跳转微信小程序
    • 圆角TabBar
    • 大屏Header
    • Echarts中国地图
    • 使用computed拦截v-model
    • 消息订阅与发布
    • Html相对路径页面跳转
    • Vite打包本地访问
    • H5主题切换
    • 移动端列表分页
    • 每次进入页面都触发的功能(v3)
    • 智能导诊
    • js中几个优雅的运算符使用技巧
    • 其他CSS伪元素
    • 微信浏览器保存canvas海报
    • uniappH5手动拖拽缩放自定义绘制海报
    • uniapp小程序盒子拖拽排序
    • 微信小程序地图的使用
    • css静态漏斗绘制
    • 微信小程序图片流处理
    • ios时间问题
    • 文字围绕效果
    • 表格树动态计算
    • React中useEffect用法
    • React Hooks 陷阱
      • Naive UI修改默认样式
      • vue 根据div id 滚动到指定view到可视视图中
      • js将[1,2,3]排列组合成[1.12.123]
      • 移动端如何加载vite导出dist包
      • TS探索接口、泛型和自定义类型
      • WebSocket中加入Token
      • 幂方程指数衰减
      • pageSpy
      • 表格多条件搜索
      • axios get 请求 url 转码 空格转成+,导致请求失败
      • NaiveUI使用Message组件遇到的问题记录
      • 小程序多盒子拖拽排序
      • 对象快速筛key方法
      • 倒计时
      • nuxt3中的useAsyncData使用详解
      • nuxt3文件式路由
      • 播放amr格式音频
      • echarts瀑布图
      • vue中使用vueuse进行文件导出
      • 分享一个数据整理方法
      • naiveui表格shift多选
      • 数组递归转tree
      • 自定义指令图片懒加载
      • 将数组里面的对象转换成我们需要的键值对
      • 亚马逊云s3上传
      • 上拉加载更多封装
      • JS设计模式总结笔记
      • 适配移动端页面顶部安全区域
      • 【CryptoJS】使用介绍
      • 微信小程序富文本图片点击放大
      • 微信小程序省市区级联选择
      • uniapp拖动排序插件
      • element ui 的树形结构懒加载,局部更新
      • 表单搜索过滤空值
      • 判断设备类型
      • tsconfig配置打包问题
      • vant-uploader上传组件添加长按保存图片
      • BroadcastChannel跨页面通信
      • pnpm安装问题
      • echart阶梯图形绘制
      • js根据对象拼接参数
      • 集成免密登录
      • 输入框输入数字限制
      • js控制全局css变量
      • 流程图
      • 修改npm包
      • tsx在vue3中的应用
      • 109video播放视频流
      • echart默认展示某个点的tooltip
      • 大屏适配几种方案
      • 表单低代码自定义列表页
      • 表单低代码列表页配置端代码
      • 低代码平台使用的一些好用的js方法
      • vue3cookie的使用
      • 原生js下载文件
      • stompjs 创建socket,断线重连机制
      • iframe作为内嵌网页cookie设置
      • 前端对文件内容解析生成特定算法哈希值方法
      • vue3中前端自定义命名文件名称下载文件的方法
      • 前端项目中权限判断的方法配合路由守卫使用
      • 原生table:表格table中thead固定,tbody超出高度出现滚动条
      • vue中使用原生的方法
      • vue3中amchart的初步使用
      • base64图片加水印
      • 手写签名
      • base64转doc文件
    • 前端
    • 技术沉淀
    商会林
    2024-04-14
    目录

    React Hooks 陷阱

    # React Hooks 陷阱

    • react 函数组件 + hook 为我们带来了,很多的方便,但同时也会遇到一些陷阱
    • hooks必须在函数顶层 ,不能在条件分支内 ,那么你踩到了那些坑 ?

    # 1、useState 陷阱

    陷阱:【异步陷阱】

    function Index() {
      const [count, setCount] = useState(0);
      
      function add(){
      	setCount( count + 1 );
      	console.log(count);  // 0
      }
      return (
      	<div>
    		<span>{count}</span>
    		<button @click=()=>{ add() }> + </button>
     	</div>
      );
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    • 点击添加按钮,发现值更新了,打印的值却还是上次的
    • 什么 useState 修改状态 是异步

    解决方法:

    • 所以我们不能修改后,把值去拿去其他操作 (应该拿 count+1)
    • 可以通过 promise 来 .then 获取 最新 👇 陷阱:【只更新最后1个】
    function Index() {
      const [count, setCount] = useState(0);
      
      function add(){
      	setCount( count + 1 );
      	setCount( count + 2 );
      	setCount( count + 3 );
      }
      return (
      	<div>
    		<span>{count}</span>
    		<button @click=()=>{ add() }> + </button>
     	</div>
      );
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    • 此时 只执行了 最后一个 setCount , 导致数据不是部分逻辑未执行
    • 如果出现这种 判断条件多次 操作 useState 怎么解决 👇
      function add(){
      	let num = count;
      	if(...) { num += 1; }
      	if(...) { num += 2; }
      	if(...) { num += 3; }
      	setCount( num );
      }
    
    1
    2
    3
    4
    5
    6
    7

    # 2、useEffect 陷阱

    陷阱:【过期闭包】

    function Index() {
      const [count, setCount] = useState(0);
      
      useEffect(()=>{
        setInterval(() => {   console.log(`Count: ${count}`)  }, 1000);
      }, []);
     
      return (
      	<div>
    		<span>{count}</span>
    		<button @click=()=>{ setCount(count+1) }> + </button>
     	</div>
      );
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    • 通过计时器,每 1 秒 打印下 count
    • 点击按钮,count 已增加 ,打印的值一直不变
    • 说明此时的 useEffect 中的 count ,还是取的 过期的值

    解决方法:

    • 需要,添加依赖项 count ,
    • 并且每次更新,添加计时器,结束改变计时器
    function Index() {
      const [count, setCount] = useState(0);
      
      useEffect(()=>{
       	const time = setInterval(() => {   console.log(`Count: ${count}`)  }, 1000);
      	return () => { clearInterval(time) };
      }, [count]);
     
      return (
      	<div>
    		<span>{count}</span>
    		<button @click=()=>{ setCount(count+1) }> + </button>
     	</div>
      );
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    # 3、useCallback 陷阱

    • useCallback 本来拿来优化性能,当依赖变化不用重新注册该函数
    • 使用不当也会,出现一定的问题

    陷阱:【获取父组件的值,不是最新】

    function Parent() {
      let [count, setCount] = useState(0);
      return (
        <div>
          <button onClick={() => setCount(count+1)}> +1 </button>
          // 子组件
          <Child count={count} />
        </div>
      );
    }
    
    function Child(props){
      let log = useCallback(() => {  console.log(props.count)  }, [])
      return (
        <div>
          count: {props.count}
          <button onClick={() => log()}> 打印 </button>
        </div>
      );
    
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    • 此时我们在 父组件点击 增加按钮
    • 子组件的 count 发生改变 ,我们在点击打印按钮,发现count 一直是0
    • 说明useCallback 依赖为【】数组,取到count 已经过期了 解决方法:
    • 方法1 :等于没有优化 (依赖更新,useCallback重写一次)
      let log = useCallback(() => {  console.log(props.count)  }, [props.count])
    
    1
    • 方法2 :将获取 count 的方法 创建到父组件,子组件调用父组件方法
      function Parent() {
      let [count, setCount] = useState(0);
      let log = useCallback(() => {  console.log(count)  }, [])
      return (
        <div>
          <button onClick={() => setCount(count+1)}> +1 </button>
          // 子组件
          <Child count={count} log={log} />
        </div>
      );
    }
    
    function Child(props){
      return (
        <div>
          count: {props.count}
          <button onClick={() => props.log()}> 打印 </button>
        </div>
      );
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    上次更新: 2024/04/14, 17:23:46
    React中useEffect用法
    Naive UI修改默认样式

    ← React中useEffect用法 Naive UI修改默认样式→

    最近更新
    01
    base64转doc文件
    01-03
    02
    手写签名
    01-03
    03
    base64图片加水印
    01-03
    更多文章>
    Theme by Vdoing | Copyright © 2023-2025 Adinnet
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式