[譯] React 16.3(.0-alpha) 新特性

言歸發表於2018-02-13

React 16.3(.0-alpha) 新特性

React 16.3-alpha 於不久前推至 npmjs,已經可以用在專案中了,你最關心哪些變化呢?

2018 年 2 月 5 日更新 —— 之前我誤解了 createContext 的一些行為,所以更新了這一節的內容,主要為了反映出工廠方法的一些行為。

全新的 context API

Context API 一直很神祕 —— 本來它是一個官方推出的、文件化的 API,但開發者們又提醒我們儘量不要用這個 API,因為這個 API 還沒完全確定下來,以後可能會再作修改,而且文件尚不完備。不過,是時候讓它發光發熱了,RFC 流程已經通過了,新的 API 程式碼也已經合併了,用起來也更加順手了。至少在狀態管理這方面,如果專案並不複雜的話,完全可以不用 Redux 和 MobX。

新的 API 方法主要體現在 React.createContext() 上,呼叫之後會建立兩個元件:

[譯] React 16.3(.0-alpha) 新特性

呼叫 React.createContext() 建立一個上下文(context)物件

這個工廠方法返回的物件包含“Provider”和“Consumer”兩個屬性,即上文提到的兩個元件。

Provider 元件用來為其所有子層級元件提供資料,示例如下:

[譯] React 16.3(.0-alpha) 新特性

在上圖中,將需要接受資料的元件放在 ThemeContext.Provider 下,設定其 value 屬性,用來存放需要傳遞的資料。當然這個 value 也可以是動態變化的(用 this.setState)。

接下來設定 Consumer 元件:

[譯] React 16.3(.0-alpha) 新特性

如果你把 Consumer 元件放在了 Provider 元件的外部(不在它的下面),其值會預設使用呼叫 createContext 時傳入的值。

PS:

  • Consumer 元件只能獲取到對應的 Context 裡設定的資料,即使新建立了一個 Context,傳入和已有的 Context 一樣的引數,不屬於這個 Context 的 Consumer 是獲取不到它設定的資料的。所以,不妨把 Context 看成一個元件,相同用途的 Context 只建立一次,再根據需要作匯入匯出(export/import)。
  • 新的寫法採用的是”方法即子元件模式”(即 function as child pattern,有時也稱作 render prop 模式),如果你對這種模式很陌生,可以參考這裡
  • 新的 API 不用再通過 prop-types 設定 contextProps 了。

Consumer 下的 context 引數對應了 Provider 元件裡設定的 value 屬性,修改 Provider 裡設定的資料會導致對應的 Consumer 下的元件重新渲染。

新的生命週期方法

另一個促使其進入 alpha 階段的 RFC 和某些生命週期方法的廢除有關,同時也還會引進一個(譯者注:其實還有另外三個方法 —— 要廢除的生命週期方法前面加個“UNSAFE_”字首構成的新方法)新的方法。

這些改變旨在引導開發者作出最佳實踐(將被廢除的這些生命週期方法頗具坑點,具體可以參考我寫的另一篇文章),這也有益於適應將來全面開放的非同步渲染模式(這也是 React 16 “Fiber” 的首要目標)。

即將被廢除的方法如下:

  • componentWillMount —— 即將廢除,使用 componentDidMount 作為替代
  • componentWillUpdate —— 即將廢除,使用 componentDidUpdate 作為替代
  • componentWillReceiveProps —— 即將廢除,使用新引進的方法 static getDerivedStateFromProps

不要瞎慌,這些方法現在都可以正常使用,不影響,到 16.4 版本才會正式打上“已廢除”的標記,真正移除可能要到 17.0 以後。

[譯] React 16.3(.0-alpha) 新特性

Dan 表示,“故事還長,大家別慌”,然而仍有群眾表示恐慌。

如果你開啟了 StrictMode 或是 AsyncMode,它只會提示你方法已經廢除了,不想看到這些提示資訊可以使用如下方法替代:

  • UNSAFE_componentWillMount
  • UNSAFE_componentWillReceiveProps
  • UNSAFE_componentWillUpdate

靜態方法:getDerivedStateFromProps

既然 componentWillReceiveProps 要被廢除了,那麼,還有其他的方法能根據 prop 的改變更新 state 嗎(不推薦使用這種開發模式)?這裡就要用到新引進的那個靜態方法了。

這裡說的靜態和其他語言的概念是一樣的,它是存在於類自身的方法,不依賴例項的建立。與一般的類方法的區別在於它不能訪問 this 關鍵字,還有就是方法前面有個 static 修飾符。

嗯,那行,但是有一個問題,既然訪問不到 this 了,那還怎麼用 this.setState 來更新狀態呢?答案是,“壓根就不需要用這個方法了”,你只需要返回新的狀態就行了,直接 return 出去,不需要用方法去設定。如果不需要更新狀態,返回 null 就行了:

[譯] React 16.3(.0-alpha) 新特性

此外,返回值的機制和使用 setState 的機制是類似的 —— 你只需要返回發生改變的那部分狀態,其他的值會保留。

敲黑板:

[譯] React 16.3(.0-alpha) 新特性

說了這麼多,還是要提醒下各位記得在構造器裡初始化一下 state(在構造器裡或者用 class field),不然就會報上面的錯誤。


這個方法在元件首次掛載和將要重新渲染的時候會呼叫,所以你可以在它裡面初始化狀態,來代替在建構函式裡面初始化。


[譯] React 16.3(.0-alpha) 新特性

如果同時定義了 getDerivedStateFromPropscomponentWillReceiveProps,只有 getDerivedStateFromProps 會被呼叫,同時 React 還會列印出警告資訊。


還有一種情況就是,當狀態發生變化的時候需要執行回撥,這時候你就可以用 componentDidUpdate


如果你覺得 static 不夠優雅,你可以用下面這種方式定義,效果是一樣的:

[譯] React 16.3(.0-alpha) 新特性

StrictMode

Strict mode 是新加入的元件,旨在引導你遵循最佳實踐。把需要進行約束的元件簇放在它的下面就完事了:

[譯] React 16.3(.0-alpha) 新特性

完全一變相的 'use strict'

如果其下的元件不小心用了上文提到的要廢除的生命週期方法,控制檯會列印出錯誤資訊(開發環境下):

[譯] React 16.3(.0-alpha) 新特性

錯誤資訊提供的連結地址目前指向的是一個 RFC issue,也是因為生命週期方法被廢除導致的。

AsyncMode

為了配合 StrictMode,非同步元件支援現在重新命名為 React.unsafe_AsyncMode,它也會引發 StrictMode 的警告資訊。

有關非同步元件的使用可以參考以下博文:

新版 React 開發工具

新版本的開發工具也已經跟進,可以識別新加入的元件了。

但是 Chrome 上的外掛還沒有更新,還要等一段時間,所以 debug 的時候會看到很有趣的東西:

[譯] React 16.3(.0-alpha) 新特性

React. __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED(譯者注:紅頭元件,用了你就怕是要被炒魷魚了)表示不服。

Firefox 使用者就有福了,完全支援:

[譯] React 16.3(.0-alpha) 新特性

可以看到 AsyncMode 元件可以直接被識別。

後日談

總之呢,這還只是 alpha 版本,等穩定版本出來的時候可能會有點改動。根據 Dan 的說法,穩定版差不多下週就出:

[譯] React 16.3(.0-alpha) 新特性

講道理,這不已經過了一個星期嗎?


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章