网站首页 > 技术文章 正文
大家好,我是前端西瓜哥。
最近在尝试优化 React 组件,使用了 React.memo() 去缓存组件的渲染结果。
但有一个问题,就是要使 React.memo() 的缓存生效,需要保持 props 对象的浅比较结果为 true。
所以我们需要通过 useCallback 或 useMemo 处理一些对象类型的 prop,让它们保持指向原来的内存对象。
在 props 少的时候还好,但一旦多了之后,我们就比较难通过肉眼确认是哪个 prop 导致缓存失效。
怎样才能够方便地知道 props 的哪个属性发生了改变呢?
你可以试试 useWhyDidYouUpate。
useWhyDidYouUpate
useWhyDidYouUpate 是一个第三方 React Hooks,来自优秀的 ahooks 库。
名字很直白:Why did you update,意思就是 “你(组件)为什么更新了?”。
顾名思义,useWhyDidYouUpate 的作用是 帮助开发者排查是哪个属性改变导致了函数组件重渲染。
用法很简单,传入一个标识符字符串(通常为组件名)、以及要进行对比的对象(通常为 props)。
useWhyDidYouUpdate('Counter', props);
useWhyDidYouUpdate 会保存好上一次传入的 props,然后和新传入的 props 进行比较,找出不同的属性,将它们打印到控制台。
我们来看个示例:
import { useWhyDidYouUpdate } from 'ahooks';
import { useState } from 'react';
function Counter(props) {
useWhyDidYouUpdate('Counter', props);
return (
<div>
<div>{props.title}</div>
<div>{props.count}</div>
</div>
);
}
export default function App() {
const [count, setCount] = useState(0);
return (
<div className="App">
<button onClick={() => setCount(count + 1)}>+ 1</button>
<Counter title={'计数显示'} count={count} />
</div>
);
}
点击 “+ 1” 按钮,然后就会在控制台看到下面输出:
这样我们就可以知道,是因为 count 从原来的 0,变成了现在的 1,导致了 Counter 组件的更新。
在线 demo:
https://codesandbox.io/s/u279ov?file=/src/App.js
实现
useWhyDidYouUpdate 的实现不是很复杂,我们直接贴源码(去掉 TS 类型标注)分析一下。
function useWhyDidYouUpdate(componentName, props) {
const prevProps = useRef({});
useEffect(() => {
if (prevProps.current) {
// 提取新旧 props 的属性,生成数组
const allKeys = Object.keys({ ...prevProps.current, ...props });
const changedProps = {};
allKeys.forEach((key) => {
// 对比 新旧 prop[key],如果不同,记录到对象中
if (!Object.is(prevProps.current[key], props[key])) {
changedProps[key] = {
from: prevProps.current[key],
to: props[key],
};
}
});
if (Object.keys(changedProps).length) {
// 输出到控制台
console.log('[why-did-you-update]', componentName, changedProps);
}
}
// 更新 prevProps
prevProps.current = props;
});
}
首先用 useRef 来声明一个 prevProps 变量,用来保存上一次的 props。
函数组件中,ref 可以实现类组件的实例属性的效果,确保每次渲染时可以保持原来的值。
然后将新旧 props 对象的属性提取出来,生成一个属性数组 allKeys。
遍历这个数组,去对比新旧 prop[key]。如果不同,记录到 changedProps 对象中。
最后输出改变的内容,并更新 prevProps。
结尾
当你尝试通过 React.memo() 给组件添加缓存时,却发现没能按照预期触发缓存,想要看看是哪个 props 发生了变化。
那么,你可以用 useWhyDidYouUpdate 来检查到底是哪些 prop 发生了改变。
当然不仅限于 props,我们也可以用 state 或其他对象上。
我是前端西瓜哥,欢迎关注我,学习更多前端知识。
- 上一篇: 移动端线上页面在没有开发者权限的情况下如何能转成pc端调试
- 下一篇: 在CLion中调试c语言
猜你喜欢
- 2024-11-19 记某次常规js前端逆向
- 2024-11-19 前端代码安全与混淆
- 2024-11-19 前端抓包神器--whistle
- 2024-11-19 使用chrome调试工具解决问题(六)
- 2024-11-19 使用chrome调试工具解决问题(七)
- 2024-11-19 使用chrome调试工具解决问题(五)
- 2024-11-19 使用chrome调试工具解决问题(四)
- 2024-11-19 使用chrome调试工具解决问题(三)
- 2024-11-19 楼宇自控系统设备的安装与调试
- 2024-11-19 使用chrome调试工具解决问题(一)
你 发表评论:
欢迎- 最近发表
-
- 前端流行框架Vue3教程:13. 组件传递数据_Props
- 前端必看!10 个 Vue3 救命技巧,解决你 90% 的开发难题?
- JAVA和JavaScript到底是什么关系?是亲戚吗?
- Java和js有什么区别?(java和javascript的区别和联系)
- 东方标准|Web和Java的区别,如何选择这两个专业
- 前端面试题-JS 中如何实现大对象深度对比
- 360前端一面~面试题解析(360前端笔试)
- 加班秃头别慌!1 道 Vue 面试题,快速解锁大厂 offer 通关密码
- 焦虑深夜刷题!5 道高频 React 面试题,吃透 offer 稳了
- 2025Web前端面试题大全(整理版)面试题附答案详解,最全面详细
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端md5加密 (49)
- 前端路由 (55)
- 前端数组 (65)
- 前端定时器 (47)
- 前端懒加载 (45)
- 前端接口 (46)
- Oracle RAC (73)
- oracle恢复 (76)
- oracle 删除表 (48)
- oracle 用户名 (74)
- oracle 工具 (55)
- oracle 内存 (50)
- oracle 导出表 (57)
- oracle查询数据库 (45)
- oracle约束 (46)
- oracle 中文 (51)
- oracle链接 (47)
- oracle的函数 (57)
- mac oracle (47)
- 前端调试 (52)
- 前端登录页面 (48)
本文暂时没有评论,来添加一个吧(●'◡'●)