[英]React: Changing Context in Consumer
以下問題與 React Context 文檔中的以下部分有關:
免責聲明:對以下所有背景信息深表歉意。 它提供了背景信息,希望對未來的訪問者有所幫助。
我們所知道的
themes.dark
(一個包含兩個屬性的對象: foreground
和background
)Consumer
上方沒有Providers
時才使用默認值App
) 中存在一個Provider
Provider
( App
),將它自己的state
作為上下文值傳遞下去Provider
的值在結構和類型上與默認上下文值相同是明智的(避免Consumers
感到困惑)App
) 中的state
持有與默認上下文值相同格式的對象: themes.light
Consumer
讀取context 時,它讀取App
的狀態App
) state
,而不必通過中間的每個組件傳遞它App
) 中的 state 發生變化時,它會重新渲染並將 state 的新值提供給Consumer
Consumer
通過上下文讀取父級的state
state
的函數( toggleTheme
)作為普通prop
向下傳遞到組件樹context
僅包含讀取state
的對象Consumer
通過傳遞setState
功能作為一個正常的prop
從Provider
的孩子,向下通過所有的中間組件,以及向Consumer
App
) 中設置state
會導致自身重新呈現,從而導致重新呈現Provider
,然后將新的App
state
值通過上下文傳遞給它的Consumer
Consumer
總是通過上下文知道App
的狀態state
作為上下文值提供給子Consumer
state
Provider
看到上下文值( App
的state
)已更改,並使用新值重新呈現其所有Consumer
。setState
函數來在Consumer
設置state
prop
來設置state
問題
我們從文檔中知道:
每個 Context 對象都帶有一個 Provider React 組件,該組件允許使用組件訂閱上下文更改......
每當 Provider 的 value 屬性發生變化時,所有作為 Provider 后代的消費者都會重新渲染。
App
使用一個普通變量作為上下文值。 我們從上面的引用中知道,更改它會導致Provider
重新渲染。 那么,我們為什么要費心使用state
作為上下文值呢? 與僅在App
使用任何普通變量相比,這樣做有什么好處?state
。 為什么鏈接 2 包含在state
本身內更新state
的功能? 我們能否將它作為一個單獨的setState
函數,通過具有兩個屬性(一個是state
,另一個是更新state
的獨立函數)的對象中的上下文傳遞給Consumer
?假設我們在 App 中使用一個普通變量作為上下文值。 我們從上面的引用中知道,更改它會導致 Provider 重新渲染。 那么,我們為什么要使用狀態作為上下文值呢? 與僅在 App 中使用任何普通變量相比,這樣做有什么好處?
確實,當使用更改的值重新呈現提供者時,任何關心上下文的后代都會重新呈現。 但是您首先需要一些東西來使提供者重新呈現。 當 App 的 state 或其 props 發生變化時(或者當你調用 forceUpdate,但不要那樣做)時,就會發生這種情況。 據推測,這是在您的應用程序的頂部,所以沒有道具進來,這意味着您將使用 state 使其重新渲染。
上述兩種方法都允許我們更新狀態。 為什么鏈接 2 包含在狀態本身內更新狀態的功能? 我們能否將它作為一個單獨的 setState 函數,通過具有兩個屬性(一個是狀態,另一個是更新狀態的獨立函數)的對象中的上下文傳遞給消費者?
當決定是否由於上下文的變化而重新渲染后代時,react 基本上會在舊值和新值之間做一個===
。 這非常快,並且適用於 React 對不可變數據的偏好,但是當使用對象作為您的值時,您需要小心不要在每次渲染時都創建新對象。 例如,如果 App 正在做類似下面的事情,它會在每次渲染時創建一個全新的對象,因此將強制所有上下文消費者也重新渲染:
class App extends Component {
state = {
data: {
hello: 'world',
}
}
updateData() {
// some function for updating the state
}
render() {
return (
<MyContext.Provider value={{
data: this.state.data,
updateData: this.updateData
}} />
)
}
}
因此,他們將函數存儲在狀態中的示例是確保他們提供的整個值不會從一個渲染更改為另一個渲染。
假設我們在 App 中使用一個普通變量作為上下文值。 我們從上面的引用中知道,更改它會導致 Provider 重新渲染。 那么,我們為什么要使用狀態作為上下文值呢? 與僅在 App 中使用任何普通變量相比,這樣做有什么好處?
當你使用 state 並更新它時——不管你是否使用提供者——所有的提供者和它下面的組件都會更新。 那是在官方 React Context 文檔下,是錯誤的。 這意味着更改提供者值根本不會調用消費者更新。
您可以通過創建一個帶有狀態的單獨組件(不會在提供者內部)來驗證這一點,並將該狀態變量分配給提供者。 因此,當組件狀態發生變化時,狀態中的值發生變化,提供者應該注意到這一點並更新消費者。 它沒有做。
不幸的是,為了更新消費者下的組件,您必須手動進行。 除非您的意圖是更新提供程序下的所有內容。
在 React 17.0.2 下,截至 2021 年 4 月 21 日,情況確實如此——提供者值的變化沒有被監控,消費者也沒有被更新。 除非您將所有提供程序都放在帶有狀態的組件中,但更改其狀態會強制更新提供程序下的所有組件。 可悲。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.