【翻譯】React 16.3 新的生命週期和context api

2014_發表於2018-04-22

文章首發於我的個人github部落格

這裡是原文連結

一段時間以前,我們寫了一篇文章有關我們即將升級我們遺留的生命週期方法,包含著我們慢慢的遷移的策略。在React 16.3.0這個版本中,為了慢慢遷移,我們增加了一些新的生命週期。我們也推薦了一些被長期期待的一些特性:一個官方的context api,一個 forwarding ref,一個ergonomic ref。

Official Context API

這麼長時間以來,React一直提供了一個實驗性的api context.儘管它是一個很有用的工具,我們還是不推薦使用它因為一些隱藏的問題。而且我們一直計劃去用一個更好的api去替代它。

16.3這個版本引入了一個新的context api,它更加的高效,而且他支援各種靜態型別檢查和很深層次的更新。
這有一個例子來說明,你可以想象你注入了了一個“theme”變數去使用新的api

const ThemeContext = React.createContext("light")
class ThemeProvider extends React.Component{
    state = {theme: 'light'}
    render(){
        return (
            <ThemeContext.Provider value={this.state.theme}>
                {this.props.children}
            </ThemeContext.Provider/>
        )
    }
}
class ThemeButton extends React.Component{
    render(){
        return (
            <ThemeContext.Consumer>
                {theme => <Button theme={theme} />}
            </ThemeContext.Consumer>
        )
    }
}複製程式碼

createRef Api

以前,react提供兩種方式去管理refs,一個是字串api,另一個是通過回撥函式。儘管字串這種方法是兩種中最方便的,但是他有一些不完善的地方,所以我們官方建議是用回撥去替代它。
16.3版本中提供了一個新的選項去管理refs,它和字串方式一樣便利,卻沒有它的缺點。

class MyComponent extends React.Component{
    constructor(props){
        super(props)
        this.inputRef = React.createRef()
    }

    render(){
        return <input type="text" ref={this.inputRef} />
    }

    componentDidMount(){
        this.inputRef.current.focus()
    }
}複製程式碼

forwardRef Api

通常,React元件是宣告式的,但是有些時候有不可避免的會使用一些dom節點在元件的例項中。很通常的一些情況比如管理聚焦,選擇或者動畫。React提供了refs作為一種方式去解決這個問題。然而,元件封裝提出了一些挑戰。

例如,如果你用元件替代了,繫結在原先元件的ref屬性值就開始指向了外層的包裹元件而不是DOM節點(在函式式的元件中將會是null),這就是被稱讚的“application-level”元件就像評論元件一樣需要被包裝,它能夠干擾葉子節點,例如FancyButon元件,他們的使用方式就和dom節點一樣,或許他們還會暴露出他們的DOM節點。

Ref forwarding是一個新的特性,讓許多元件能夠接收ref,並且傳給它的子元件。eg:

const FancyButton = React.forwardRef((props,ref) => {
    <button ref={ref} className="FancyButton">
        {this.prop.children}
    </button>
})
const ref = React.createRef()
<FancyButton ref={ref}>click,/FancyButton>複製程式碼

用這種方式,組建可以將erf傳遞給DOM button,並且需要的話連線它,就像直接在使用一個dom元件。

當然,ref forwarding並不僅侷限於向葉子元件渲染dom節點,如果你編寫高階元件的話,我們建議你用它自動的向那些被包裹的元件傳遞ref。

Component Lifecycle Changes

React元件的api已經很久沒有改動了。然而,當我們新增了一些新特性(出錯處理和非同步渲染)之後,我們延伸出了這種模型儘管他並不是我們最初計劃的。

例如,利用現有的api,很容易就可以阻止最初的渲染。這是因為有太多的過程去完成一次渲染。我們研究發現,出錯行為的處理並沒有被考慮進去,這樣就會導致記憶體洩漏。而且現在的元件也讓其他過程複雜化。

這些問題使得元件的生命週期被濫用。(componentWillMount,componentWillReceiveProps,componentWillUpdate)。而且令我們困惑的是這些錯誤經常發生在生命週期中。根據這些原因,我們決定使用一些更好的選擇。

我們知道這些改變會影響很多已有的元件。因此,我們會盡可能慢慢的遷移,而且我們會提供一些別的方法。

我們為了放棄這些不安全的生命週期,我們提供了幾個新的:

  • getDerivedStateFromProps:替代componentWillReceiveProps這個生命週期更加安全的方法
  • getSnapshotBeforeUpdate: 為了支援在元件更新前更加安全的讀取屬性

最後,附上這次api更新嚐鮮的demo


相關文章