React Hook 如何實現當子元件 props 不變不隨父元件一起重渲染

時間 2021-05-29 23:02:54

1樓:龍背上的騎兵

使用自定義compare函式.

其實題主的意思就是實現shouldComponentUpdate的方法,可以精確控制哪些prop才能導致重繪。

這個功能很容易想到React.memo , 預設情況下 React.memo 會使用props的shadowEqual來對比,滿足大部分場景。

但是例如defaultValue這種非受控屬性當它變化時沒必要去重繪元件, 所以就需要手動定製比較函式。使用React.memo(Component, compare)即可實現。

和shouldComponentUpdate不同的是,compare為 true表示是相同屬性,不重繪,反之才重繪,和`shouldComponentUpdate`剛好相反。

function

Input

()function

isSameInput

(props

,newProps

)export

default

React

.memo

(Input

,isSameInput);

2樓:伊撒爾

很多方法

現成的,使用 memo,對元件進行包裹,這樣 props 就會進行淺比較

const component = memo(Component)

hooks 中的 useMemo 可以用來快取函式

const component = useMemo(() => , [props.a])

這兩個是有區別的,前者是props 的淺比較,比較看看要不要clone子元素,後者是比較props,然後快取這個函式,然後根據 props 變化,對比這兩個元件

我認為後者更好,因為這種比較是相對比較嚴格的,更安全可靠

當然還有一點很重要,memo 是針對元件的快取,但是實際上,需要快取的不只是元件,jsx 的任何一部分都可以被快取,所以 useMemo 更加通用而且符合語義

其實這裡有乙個很遠古的問題。說到底是 h 函式的問題

因為 render 都會重新 h 一堆 jsx,導致每次生成的都是新的,後來大家發現,這樣效能並不好,於是就有人反其道而為之

其中比較徹底的是 vue3,它做了一下幾件事情

將靜態的 jsx 元素全域性提公升,保證只 h 一次(相當於自動 useMemo)

將一些 handler 進行快取,保證這些函式只生成一次(相當於自動 useCallback)

內建 props 的淺比較(相當於自動 memo)

做了這一堆,其實就是快取 jsx,讓他們能夠進行比較,無論是淺比較還是嚴格相等

這樣做的好處是,大部分 case 是可以提公升效能而且符合中國人思維的

那為什麼 react 和 jsx 外掛程式不做這些事情呢?其實真的一直很迷

這是 dan 給的回覆:React.memo() by gaearon · Pull Request #63 · reactjs/rfcs

他認為淺比較不靠譜而且每個元件都去遍歷 props 的效能也不好

我還問過別人,還有人說向後相容,為了相容過去眾多 react 元件

當然其實不內建也沒有關係,這樣依賴,就全靠使用者的編碼能力了,使用者一定要有對 jsx 進行 memo 的概念,這樣一樣可以寫出非常精確的效能

然後就是關於 fre,我會在 fre2 中移除 memo,因為基於 memo 的這種 props 的淺比較不如 useMmemo 的陣列比較更可靠,不過為了找到一種權衡,fre 可能會這樣:

如果能夠嚴格相等 === ,那麼 fre 就會盡可能在框架內部處理如果是淺比較/陣列依賴的比較,這種比較通常來說是不可靠的,不應該由框架內建

什麼情況下可以嚴格對等呢?那就是你利用 memo 去快取引用的時候

所以 reactor 一定要有 memo 的概念了

3樓:

當Parent re-render時,Child也會re-render,除非以下2種情況之一發生:

父元件渲染的JSX tree中,在某個位置使用的物件(react element,即React.createElement()返回的物件)與上次渲染時相同(在同乙個位置使用同乙個物件引用),這時Child元件不會re-render。

Child元件被React.memo裝飾,並且傳給Child元件的props與上次渲染相同。

這種情況可以理解為React.memo幫我們快取了上次渲染時使用的jsx element物件。即:

const Component = React.memo(() =>

})等價於

const Component = () =>

count]) // deps陣列包含所有Parent可能傳入的props value

}demo:

white-currying-c94hn - CodeSandbox

詳細解釋見我的React效能優化總結:

【React效能優化總結】React元件什麼時候重新渲染?如何做效能優化? - csRyan的學習專欄 - SegmentFault 思否

4樓:verySao

類元件中我們通過 shouldComponentUpdate 生命週期或繼承 React.PureComponent 來控制項是否重新渲染。

在函式元件中,可以通過 React.memo 或 React.useMemo 來實現相同的功能:

import

React

,from

"react"

;export

const

MemoComponent

=React

.memo

(props

=>

;

});export

const

SameMemoComponent

=props

=>;},[

props

.count

]);};

乙個建議

使用 useMemo 替代 React.memo。

因為當元件中存在 context 時,context 內容變化的話,useMemo 能更有效的進行快取:

// 當 bigContext 變化時,會導致重新渲染

const

useContextComponent

=React

.memo

(()=>

=useContext

(BigContext

);return

;

});// 使用 useMemo 優化

const

useContextComponent=()

=>=useContext

(BigContext

);return

useMemo

(()=>

;},[

someData

]);};

參考Issue:Preventing rerenders with React.memo and useContext hook.

5樓:

如果父元件給子元件傳遞的值是物件,一定注意此物件必須來自useState或者useRef、useMemo、useCallback之一,原因是React.memo生成的REACT_MEMO_TYPE Fiber在ReactFiberBeginWork階段中,判斷是否需要createWorkInProgress(建立備用Fiber並進入後續排程更新)時依賴的預設compare函式是shallowEqual。常見場景:

向下傳遞callback。

如何去合理使用 React hook?

PrimaryK 初學者都想著如何用hooks實現class component的生命週期函式.寫著寫著就把自己陷進去了.其實,React Hooks的精髓還是custom hook.我想你多看看其他人寫的custom hook應該會受益良多.學習hooks的核心是暫時的忘掉class compon...

我的人生夢想是當乙個廚師,我應該如何實現?

麻花魚 你確定要把廚子作為你一生的事業了嗎?表哥是乙個廚子,而且是乙個艱辛成長的廚子,我給你簡述一下他的歷程 1.從小喜歡幫廚,喜歡到什麼程度呢?高中畢業堅決不上大學,學廚去了 父母氣得倒仰 2.重慶這邊火鍋為主啊,連走遍全國的川菜都不是很受待見,小廚子表哥表示找不到高明的師傅 3.去了海南,因為有...

我想單身一輩子,能實現嗎?

我若成魔 為什麼不能實現啊,很好實現啊,你能自己養得起自己就行,堅持自己誰說也不管用,誰的也不聽,我命由我不由別人,老了進養老院等死,別自己待家裡省的臭了都沒人發現被老鼠吃了。 小洋沒煩惱 現實點的說也不是不可以,但要有錢。你要在想吃 想喝 想旅遊 想花錢的時候有能力,不怕孤獨,不怕流言蜚語,然後你...

其他用戶還看了: