您现在的位置是:网站首页> 编程资料编程资料
React Hook 四种组件优化总结_React_
2023-05-24
381人已围观
简介 React Hook 四种组件优化总结_React_
前言
React Hook 已成为当前最流行的开发范式,React 16.8 以后基于 Hook 开发极大简化开发者效率,同时不正确的使用 React Hook也带来了很多的性能问题,本文梳理基于 React Hook 开发组件的过程中如何提高性能。
组件抽取
优化前
每次点击 Increase 都会引起子组件 Child 的渲染,哪怕子组件并没有状态变化
function Before(){ console.log('Demo1 Parent') let [count,setCount] = useState(0) let [name,setName] = useState('-') const handleClick = ()=>{ setCount(count+1) } const handleInput = (e)=>{ setName(e.target.value) } return ( {count}
) } // 子组件 function Child(props){ console.log('Demo1 Child') return ( 子组件渲染:{props.name} ) }
优化后
只需要把 Increase 抽取成独立的组件即可。此时点击按钮,子组件并不会渲染。
/** * 优化后,Increase提取以后,上下文发生变化,组件内 * @returns */ function Increase(){ console.log('Child Increase') let [count,setCount] = useState(0) const handleClick = ()=>{ setCount(count+1) } return ( {count} ) } function After(){ console.log('Demo1 Parent') let [name,setName] = useState('-') const handleInput = (e)=>{ setName(e.target.value) } return ( ) } // 子组件 function Child(props){ console.log('Demo1 Child') return ( 子组件渲染:{props.name} ) }memo 优化组件
同样基于上述优化前代码,如果不抽取组件,使用 memo 优化后,当点击按钮后,也不会触发二次渲染。
// 优化前 function AfterMemo(){ console.log('Demo1 Parent') let [count,setCount] = useState(0) let [name,setName] = useState('-') const handleClick = ()=>{ setCount(count+1) } const handleInput = (e)=>{ setName(e.target.value) } return ( {count} ) } // 子组件 const Child = memo((props)=>{ console.log('Demo1 Child') return ( 子组件渲染:{props.name} ) })React.memo 语法
React.memo 为高阶组件,与 React.PureComponent相似。
function TestComponent(props){ // 使用 props 渲染 } function areEqual(prevProps,nextProps){ /* 如果把 nextProps 传入 render 方法的返回结果与 将 prevProps 传入 render 方法的返回结果一致则返回 true, 否则返回 false */ } export default React.memo(TestComponent,areEqual)与 class 组件中 shouldComponentUpdate() 方法不同的是,如果 props 相等,areEqual 会返回 true;如果 props 不相等,则返回 false。这与 shouldComponentUpdate 方法的返回值相反。
useCallback 优化组件
如果已经用了 memo ,当遇到下面这种场景时,同样会触发子组件渲染。比如,给 Child 绑定一个 handleClick ,子组件内部增加一个按钮,当点击子组件的按钮时,更改 count 值,即使没有发生 name 变化,也同样会触发子组件渲染,为什么?memo 不是会判断 name 变化了,才会更新吗?
function Before(){ console.log('Demo1 Parent') let [count,setCount] = useState(0) let [name,setName] = useState('-') const handleClick = ()=>{ setCount(count+1) } const handleInput = (e)=>{ setName(e.target.value) } const handleChange = ()=>{ setCount(count+1) } return ( {count} ) } // 子组件 const Child = memo((props)=>{ console.log('Demo1 Child') return ( 子组件渲染:{props.name} ) })
并不是 memo 没有生效,是因为当状态发生变化时,父组件会从新执行,导致从新创建了新的handleChange 函数,而 handleChange 的变化导致了子组件的再次渲染。
优化后
点击父组件的Increase按钮,更改了 count 值,经过 useCallback 包裹 handleChange 函数以后,我们会发现子组件不再渲染,说明每当父组件执行的时候,并没有创建新的 handleChange 函数,这就是通过 useCallback 优化后的效果。 即使我们点击子组件的按钮,也同样不会触发子组件的渲染,同样 count 会进行累加。
function After(){ console.log('Demo1 Parent') let [count,setCount] = useState(0) let text = useRef(); let [name,setName] = useState('-') const handleClick = ()=>{ setCount(count+1) } const handleInput = (e)=>{ setName(e.target.value) } const handleChange = useCallback(()=>{ // 为了让 count 能够累加,我们使用ref 获取值 let val = parseInt(text.current.textContent); setCount(val+1) },[]) return ( {count} ) }
useCallback 作用
// 用法 useCallback(()=>{ // to-do },[]) // 示例 function App(){ // 点击按钮调用此函数,但返回被缓存 const onClick = useCallback(() => { console.log('我被缓存了,怎么点击都返回一样'); }, []); return ( ); }useCallback接收 2 个参数,第一个为缓存的函数,第二个为依赖值- 主要用于缓存函数,第二次会返回同样的结果。
useMemo 优化
我们定义了一个total函数,内部使用 1 填充了100次,通过 reduce 计算总和,经过测试发现点击 Increase按钮后,只会执行 total1 ,不会执行 total2,假设total计算量巨大,就会造成内存的浪费,通过 useMemo 可以帮我们缓存计算值。
function Before(){ console.log('Demo1 Parent') let [count,setCount] = useState(0) const handleClick = ()=>{ setCount(count+1) } const total1 = ()=>{ console.log('计算求和1') let arr = Array.from({ length:100 }).fill(1) return arr.reduce((prev,next)=>prev+next,0) } // 缓存对象值 const total2 = useMemo(()=>{ console.log('计算求和2') let arr = Array.from({ length:100 }).fill(1) return arr.reduce((prev,next)=>prev+next,0) },[count]) return ( {count} {total1()} {total2} ) }
useMemo 语法
相关内容
- vue中监听input框获取焦点及失去焦点的问题_vue.js_
- vue项目中销毁window.addEventListener事件监听解析_vue.js_
- 浏览器视频帧操作方法 requestVideoFrameCallback()_javascript技巧_
- element-ui表单提交自动清空隐藏表单值实现_vue.js_
- JavaScript垃圾回收机制(引用计数,标记清除,性能优化)_javascript技巧_
- vue中this.$createElement方法的使用_vue.js_
- vue基础ESLint Prettier配置教程详解_vue.js_
- JavaScript对象与JSON格式的转换及JSON.stringify和JSON.parse的使用方法_javascript技巧_
- vue单选按钮,选中如何改变其当前按钮颜色_vue.js_
- vue data中的return使用方法示例_vue.js_
点击排行
本栏推荐
