如何優雅地處理使用 React Context 導致的不必要渲染問題?

時間 2021-05-06 16:54:56

1樓:否子戈

就題主問題。

Context 不一定引起重新渲染,可能是你姿勢不對

Child 發生 render 那個問題你 codesandbox 已經解決了, 加個 memo

既然會用 memo,為啥 Consumer 裡面不考慮用 memo?

為啥要用 context 這種醜陋的 api?

最優雅的解決 context rerender 問題的方式是:不使用 context!

看了其他答主的回答,其實感覺大家的觀點基本上都是差不多的。做 react 開發沒有必要非得抓住官方的 api 不放,使用官方 api 也不一定是效能最佳。context 的設計我覺得比較雞肋,很有可能再未來的版本中被移除。

那怎麼解決兩個遙遠跨級元件的狀態/服務的傳遞呢?

我在寫 Nautil 的時候,提供了一種叫做「汙染」的方法,同樣需要兩個元件,例如 Provider 和 Consumer 這一對。Provider 內部會採取乙個策略,汙染自己內部的所有 Consumer 在其 props 中注入 store。也就是說,你可以單獨使用 也可以不傳 store 接收來自上面很多層的 Provider 汙染的 store (都在 props 中去取)。

當然,這種比較 hack 的「汙染」方法也不保險,可能隨著 react 版本公升級又用不了了。但是這並不妨礙這種思想,就是,你不需要通過 context 來跨級傳遞狀態/服務,react 程式設計自身還是 js 程式設計,不要用了 react 忘了 js 基本操作。

另外乙個問題是如何響應跨級狀態的變化。在其他答案裡面給了很關鍵的點,就是,響應變化本質上是個訂閱模式,通過實現一套觀察者模式很容易就可以做到狀態變化的響應。題主想要做到,只對 value 的區域性做響應,那就構建一套可以對物件區域性進行觀察的系統。

比如在 Nautil 中,你可以給 Consumer 傳乙個 watch 來決定對 store 中的具體哪些屬性進行響應,比如 這樣,可以縮小響應的範圍,理論上效能更優秀。這種小粒度的依賴更新的最佳實踐非mbox莫屬。

最後,放一下 Nautil 的專案位址,求在座的各位不吝賜star

tangshuang/nautil

2樓:buhi

一句話,react context是給你注入服務的,不是讓你注入資料的,如果要注入具有資料的服務那你就注入個類似EventEmitter的東西,例如rxjs observable

3樓:馮恆智

我個人認為react官方並不在意冗餘的react render,你看看官方設計的那些api就知道了

這種寫法至少在我個人看來不符合官方的pattern

塞大物件導致的問題解決思路應該是拆成多個context/使用context以外的方案

4樓:方應杭

Context 裡面內容的改變根本就不會觸發渲染如果你希望元件只在自己依賴的資料變化時 render,可以引入 selector 並對比新舊資料

方應杭:面試官叫我手寫 Redux - 2完。

5樓:伊撒爾

其實怎麼寫都不不算錯誤,deps 的比較也是淺比較你說的知乎大v,大概還停留在之類的認知層面,信他們個鬼邪至於解法,就是 useContextSelector 和 lazily propagate

這也是我沒有在 fre 中實現 context 的原因,因為 react 現在的實現太粗暴了,或者說這種 pull 模式的全域性狀態本身就沒有好的實現思路

如何優雅地使用 Kindle?

葉里序 我強烈建議,買Kindle不要買保!護!套!我是乙個喜歡輕便的人,買完保護套套上之後,Kindle顯得非常笨重 讓我沒有想要拿在手裡的慾望,當我拿下保護套。真的不要太爽。所以建議不套保護套。Kindle挺耐摔的 小聲bb puresky simple 在主介面搜尋欄裡輸入 ds Kindle...

如何優雅地使用 Android?

手機是nexus系列,要不就刷原生的。原生體驗最好。用nova作為啟動器,再找幾個圖示包,中國產軟體乙個都不要在安卓手機上裝,嘿嘿嘿。 任浣衡 如果是像我這種對系統有潔癖的我會重新刷機建議找乙個Android5.1或Android4.4以上的Rom上面有個ART模式有別於4.4以前的rom 刷機的時...

如何優雅地使用 Vim?

安利下個人的乙個輪子 基於 vim8 neovim 的 job util,簡化各種序列並行的非同步實現 主要能幹啥事 儲存檔案 自動打包部署 執行 各種方式輸出編譯日誌 還能幹啥事 vim script 實現的輸入法,自動同步詞庫,非同步呼叫其它雲輸入法api 已登出 想要優雅的使用Vim,你需要具...