大家好,我是前端西瓜哥。 最近在尝试优化React组件,使用了React。memo()去缓存组件的渲染结果。 但有一个问题,就是要使React。memo()的缓存生效,需要保持props对象的浅比较结果为true。 所以我们需要通过useCallback或useMemo处理一些对象类型的prop,让它们保持指向原来的内存对象。 在props少的时候还好,但一旦多了之后,我们就比较难通过肉眼确认是哪个prop导致缓存失效。 怎样才能够方便地知道props的哪个属性发生了改变呢? 你可以试试useWhyDidYouUpate。useWhyDidYouUpate useWhyDidYouUpate是一个第三方ReactHooks,来自优秀的ahooks库。 名字很直白:Whydidyouupdate,意思就是你(组件)为什么更新了?。 顾名思义,useWhyDidYouUpate的作用是帮助开发者排查是哪个属性改变导致了函数组件重渲染。 用法很简单,传入一个标识符字符串(通常为组件名)、以及要进行对比的对象(通常为props)。useWhyDidYouUpdate(Counter,props); useWhyDidYouUpdate会保存好上一次传入的props,然后和新传入的props进行比较,找出不同的属性,将它们打印到控制台。 我们来看个示例:import{useWhyDidYouUpdate}fromahooks;import{useState}fromreact;functionCounter(props){useWhyDidYouUpdate(Counter,props);return({props。title}{props。count});}exportdefaultfunctionApp(){const〔count,setCount〕useState(0);return(buttononClick{()setCount(count1)}1buttonCountertitle{计数显示}count{count});} 点击1按钮,然后就会在控制台看到下面输出: 这样我们就可以知道,是因为count从原来的0,变成了现在的1,导致了Counter组件的更新。 在线demo: https:codesandbox。iosu279ov?filesrcApp。js实现 useWhyDidYouUpdate的实现不是很复杂,我们直接贴源码(去掉TS类型标注)分析一下。functionuseWhyDidYouUpdate(componentName,props){constprevPropsuseRef({});useEffect((){if(prevProps。current){提取新旧props的属性,生成数组constallKeysObject。keys({。。。prevProps。current,。。。props});constchangedProps{};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(〔whydidyouupdate〕,componentName,changedProps);}}更新prevPropsprevProps。currentprops;});} 首先用useRef来声明一个prevProps变量,用来保存上一次的props。 函数组件中,ref可以实现类组件的实例属性的效果,确保每次渲染时可以保持原来的值。 然后将新旧props对象的属性提取出来,生成一个属性数组allKeys。 遍历这个数组,去对比新旧prop〔key〕。如果不同,记录到changedProps对象中。 最后输出改变的内容,并更新prevProps。结尾 当你尝试通过React。memo()给组件添加缓存时,却发现没能按照预期触发缓存,想要看看是哪个props发生了变化。 那么,你可以用useWhyDidYouUpdate来检查到底是哪些prop发生了改变。 当然不仅限于props,我们也可以用state或其他对象上。 我是前端西瓜哥,欢迎关注我,学习更多前端知识。