最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

React?Hook?四種組件優(yōu)化總結

 更新時間:2022年07月27日 10:21:15   作者:??河畔一角?  
這篇文章主要介紹了React?Hook四種組件優(yōu)化總結,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價孩子,需要的朋友可以參考一下

前言

React Hook 已成為當前最流行的開發(fā)范式,React 16.8 以后基于 Hook 開發(fā)極大簡化開發(fā)者效率,同時不正確的使用 React Hook也帶來了很多的性能問題,本文梳理基于 React Hook 開發(fā)組件的過程中如何提高性能。

組件抽取

優(yōu)化前

每次點擊 Increase 都會引起子組件 Child 的渲染,哪怕子組件并沒有狀態(tài)變化

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>計數(shù)器:</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>
????)
}

優(yōu)化后

只需要把 Increase 抽取成獨立的組件即可。此時點擊按鈕,子組件并不會渲染。

/**
?*?優(yōu)化后,Increase提取以后,上下文發(fā)生變化,組件內(nèi)
?*?@returns?
?*/
function?Increase(){
????console.log('Child?Increase')
????let?[count,setCount]?=?useState(0)
????const?handleClick?=?()=>{
????????setCount(count+1)
????}
????return?(
????????<div>
????????????<div?className='l50'>
????????????????<label>計數(shù)器:</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 優(yōu)化組件

同樣基于上述優(yōu)化前代碼,如果不抽取組件,使用 memo 優(yōu)化后,當點擊按鈕后,也不會觸發(fā)二次渲染。

//?優(yōu)化前
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>計數(shù)器:</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 優(yōu)化組件

如果已經(jīng)用了 memo ,當遇到下面這種場景時,同樣會觸發(fā)子組件渲染。比如,給 Child 綁定一個 handleClick ,子組件內(nèi)部增加一個按鈕,當點擊子組件的按鈕時,更改 count 值,即使沒有發(fā)生 name 變化,也同樣會觸發(fā)子組件渲染,為什么?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>計數(shù)器:</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 沒有生效,是因為當狀態(tài)發(fā)生變化時,父組件會從新執(zhí)行,導致從新創(chuàng)建了新的handleChange 函數(shù),而 handleChange 的變化導致了子組件的再次渲染。

優(yōu)化后

點擊父組件的Increase按鈕,更改了 count 值,經(jīng)過 useCallback 包裹 handleChange 函數(shù)以后,我們會發(fā)現(xiàn)子組件不再渲染,說明每當父組件執(zhí)行的時候,并沒有創(chuàng)建新的 handleChange 函數(shù),這就是通過 useCallback 優(yōu)化后的效果。 即使我們點擊子組件的按鈕,也同樣不會觸發(fā)子組件的渲染,同樣 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>計數(shù)器:</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(){
??//?點擊按鈕調用此函數(shù),但返回被緩存
??const?onClick?=?useCallback(()?=>?{
????console.log('我被緩存了,怎么點擊都返回一樣');
??},?[]);

??return?(?
????<button?onClick={onClick}>點擊</button>
??);
}
  • useCallback 接收 2 個參數(shù),第一個為緩存的函數(shù),第二個為依賴值
  • 主要用于緩存函數(shù),第二次會返回同樣的結果。

useMemo 優(yōu)化

我們定義了一個total函數(shù),內(nèi)部使用 1 填充了100次,通過 reduce 計算總和,經(jīng)過測試發(fā)現(xiàn)點擊 Increase按鈕后,只會執(zhí)行 total1 ,不會執(zhí)行 total2,假設total計算量巨大,就會造成內(nèi)存的浪費,通過 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>計數(shù)器:</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]);
  • 傳入一個函數(shù)進去,會返回一個 memoized 值,需要注意的是,函數(shù)內(nèi)必須有返回值
  • 第二個參數(shù)會依賴值,當依賴值更新時,會從新計算。

useCallback 和 useMemo 區(qū)別

他們都用于緩存,useCallback 主要用于緩存函數(shù),返回一個 緩存后 函數(shù),而 useMemo 主要用于緩存值,返回一個緩存后的值。

到此這篇關于React Hook 四種組件優(yōu)化總結的文章就介紹到這了,更多相關React Hook 組件優(yōu)化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 在 React 中使用 Redux 解決的問題小結

    在 React 中使用 Redux 解決的問題小結

    在 React 中組件通信的數(shù)據(jù)流是單向的,頂層組件可以通過 props 屬性向下層組件傳遞數(shù)據(jù),而下層組件不能直接向上層組件傳遞數(shù)據(jù),這篇文章主要介紹了使用react+redux實現(xiàn)彈出框案例,需要的朋友可以參考下
    2022-10-10
  • React?腳手架配置代理完整指南(最新推薦)

    React?腳手架配置代理完整指南(最新推薦)

    本文詳細介紹了React腳手架配置代理的多種方式,文章還討論了常見問題的解決方案,如跨域問題、WebSocket代理和錯誤處理,并提供了生產(chǎn)環(huán)境配置建議和調試技巧,感興趣的朋友一起看看吧
    2024-12-12
  • React 封裝自定義組件的操作方法

    React 封裝自定義組件的操作方法

    React中自定義組件的重要性在于它們提供了代碼重用、降低耦合性、提升可維護性、更好的團隊協(xié)作、靈活性和易于測試和調試等好處,從而提高了開發(fā)效率和質量,這篇文章主要介紹了React 封裝自定義組件,需要的朋友可以參考下
    2023-12-12
  • React如何動態(tài)控制偽元素樣式

    React如何動態(tài)控制偽元素樣式

    這篇文章主要介紹了React如何動態(tài)控制偽元素樣式問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • 詳解如何在項目中使用jest測試react native組件

    詳解如何在項目中使用jest測試react native組件

    本篇文章主要介紹了詳解如何在項目中使用jest測試react native組件,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-02-02
  • useEvent顯著降低Hooks負擔的原生Hook

    useEvent顯著降低Hooks負擔的原生Hook

    這篇文章主要為大家介紹了useEvent顯著降低Hooks負擔的原生Hook示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • react+antd+upload結合使用示例

    react+antd+upload結合使用示例

    這篇文章主要為大家介紹了react+antd+upload結合使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-05-05
  • react組件中debounce防抖功能失效問題解決辦法

    react組件中debounce防抖功能失效問題解決辦法

    在React組件中,如果使用useState管理searchKey,每次輸入變化都會導致組件重新渲染,從而生成新的debounce函數(shù),導致防抖功能失效,解決方法是使用useRef定義searchKey為非響應式數(shù)據(jù),從而維持debounce函數(shù)的穩(wěn)定,確保防抖功能有效,感興趣的朋友跟隨小編一起看看吧
    2024-10-10
  • ReactHook使用useState更新變量后,如何拿到變量更新后的值

    ReactHook使用useState更新變量后,如何拿到變量更新后的值

    這篇文章主要介紹了ReactHook使用useState更新變量后,如何拿到變量更新后的值問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • react搭建環(huán)境時執(zhí)行npm start報錯start: 'react-scripts start'的解決

    react搭建環(huán)境時執(zhí)行npm start報錯start: 'react-scripts&

    這篇文章主要介紹了react搭建環(huán)境時執(zhí)行npm start報錯start: 'react-scripts start'的解決方案,具有很好的參考價值,希望杜對大家有所幫助,
    2023-10-10

最新評論

凯里市| 蓝山县| 新安县| 藁城市| 兴宁市| 襄垣县| 江孜县| 嘉鱼县| 辛集市| 西昌市| 甘孜县| 巴楚县| 通道| 嘉祥县| 孝昌县| 渝中区| 东港市| 永登县| 怀柔区| 永顺县| 闸北区| 旬邑县| 隆回县| 海城市| 潜江市| 玉林市| 额尔古纳市| 楚雄市| 平湖市| 府谷县| 邵武市| 津南区| 大荔县| 开化县| 边坝县| 大丰市| 镇平县| 年辖:市辖区| 双鸭山市| 万荣县| 岗巴县|