前言
react hook 已成为当前最流行的开发范式,react 16.8 以后基于 hook 开发极大简化开发者效率,同时不正确的使用 react hook也带来了很多的性能问题,python教程分享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 ( <div> <div classname='l50'> <label>计数器:</label> <span classname='mr10'>{count}</span> <button classname='ml10' onclick={handleclick}>increase</button> </div> <div classname='l50'> <label htmlfor="">改变子组件:</label> <input type="text" onchange={handleinput}/> </div> <hr /> <child name={name}/> </div> ) } // 子组件 function child(props){ console.log('demo1 child') return ( <div classname='l50'> 子组件渲染:{props.name} </div> ) }
优化后
只需要把 increase
抽取成独立的组件即可。此时点击按钮,子组件并不会渲染。
/** * 优化后,increase提取以后,上下文发生变化,组件内 * @returns */ function increase(){ console.log('child increase') let [count,setcount] = usestate(0) const handleclick = ()=>{ setcount(count+1) } return ( <div> <div classname='l50'> <label>计数器:</label> <span classname='mr10'>{count}</span> <button classname='ml10' onclick={handleclick}>increase</button> </div> </div> ) } function after(){ console.log('demo1 parent') let [name,setname] = usestate('-') const handleinput = (e)=>{ setname(e.target.value) } return ( <div> <increase/> <div classname='l50'> <label htmlfor="">改变子组件:</label> <input type="text" onchange={handleinput}/> </div> <child name={name}/> </div> ) } // 子组件 function child(props){ console.log('demo1 child') return ( <div classname='l50'> 子组件渲染:{props.name} </div> ) }
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 ( <div> <div classname='l50'> <label>计数器:</label> <span classname='mr10'>{count}</span> <button classname='ml10' onclick={handleclick}>increase</button> </div> <div classname='l50'> <label htmlfor="">改变子组件:</label> <input type="text" onchange={handleinput}/> </div> <child name={name}/> </div> ) } // 子组件 const child = memo((props)=>{ console.log('demo1 child') return ( <div classname='l50'> 子组件渲染:{props.name} </div> ) })
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 ( <div> <div classname='l50'> <label>计数器:</label> <span classname='mr10'>{count}</span> <button classname='ml10' onclick={handleclick}>increase</button> </div> <div classname='l50'> <label htmlfor="">改变子组件:</label> <input type="text" onchange={handleinput}/> </div> <child name={name} handleclick={handlechange}/> </div> ) } // 子组件 const child = memo((props)=>{ console.log('demo1 child') return ( <div classname='l50'> 子组件渲染:{props.name} <button onclick={props.handleclick}>更改count</button> </div> ) })
并不是 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 ( <div> <div classname='l50'> <label>计数器:</label> <span classname='mr10' ref={text}>{count}</span> <button classname='ml10' onclick={handleclick}>increase</button> </div> <div classname='l50'> <label htmlfor="">改变子组件:</label> <input type="text" value={name} onchange={handleinput}/> </div> <child name={name} handleclick={handlechange}/> </div> ) }
usecallback 作用
// 用法 usecallback(()=>{ // to-do },[]) // 示例 function app(){ // 点击按钮调用此函数,但返回被缓存 const onclick = usecallback(() => { console.log('我被缓存了,怎么点击都返回一样'); }, []); return ( <button onclick={onclick}>点击</button> ); }
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 ( <div> <div classname='l50'> <label>计数器:</label> <span classname='mr10'>{count}</span> <button classname='ml10' onclick={handleclick}>increase</button> </div> <div> <label>总和:</label> <span>{total1()}</span> <span>{total2}</span> </div> </div> ) }
usememo 语法
const memoizedvalue = usememo(() => computeexpensivevalue(a, b), [a, b]);
- 传入一个函数进去,会返回一个
memoized
值,需要注意的是,函数内必须有返回值 - 第二个参数会依赖值,当依赖值更新时,会从新计算。
usecallback 和 usememo 区别
他们都用于缓存,usecallback
主要用于缓存函数,返回一个 缓存后 函数,而 usememo
主要用于缓存值,返回一个缓存后的值。
到此这篇关于react hook 四种组件优化总结的文章就介绍到这了,更多相关react hook 组件优化内容请搜索<猴子技术宅>以前的文章或继续浏览下面的相关文章希望大家以后多多支持<猴子技术宅>!
需要了解更多python教程分享React Hook 四种组件优化总结,都可以关注python教程分享栏目—猴子技术宅(www.ssfiction.com)
本文来自网络收集,不代表猴子技术宅立场,如涉及侵权请点击右边联系管理员删除。
如若转载,请注明出处:https://www.ssfiction.com/pythons/1187938.html