React v16.3.0: New lifecycles and context API

NO IMAGE
1 Star2 Stars3 Stars4 Stars5 Stars 給文章打分!
Loading...

幾天前,我們寫了一篇關於即將到來的對我們的傳統生命週期方法的變更的文章,包括逐步遷移策略。在React 16.3.0中,我們新增了一些新的生命週期方法來幫助遷移。我們還引入了新的API,用於長時間請求的特性:一個官方的上下文API、一個ref轉發API和一個更語意化的ref API。

請繼續閱讀,瞭解更多關於這個版本的資訊。

官方認證的 Context API

多年來,React為Context提供了一個實驗性的API。雖然它是一個強大的工具,但是由於API中固有的問題,它的使用是不受歡迎的,因此我們打算用一個更好的API來替代這實驗性的API。

React 16.3引入了一個新的Context API,它更高效,同時支援靜態型別檢查和深度更新。

注意
舊的ContextAPI 將繼續保留到React 16.x,所以您將有時間遷移。

下面是一個示例,說明如何使用新的上下文API注入“主題”:

## by 司徒正美
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 ThemedButton extends React.Component {
render() {
return (
<ThemeContext.Consumer>
{theme => <Button theme={theme} />}
</ThemeContext.Consumer>
);
}
}

createRef API

以前,React提供了兩種管理refs的方法:字串ref API和回撥ref API。儘管字串ref API比較方便,但是它有幾個缺點,所以我們的官方推薦是使用回撥ref。

React 16.3為管理refs提供了一個新的方案,它為字串ref提供了方便,並且沒有任何缺點:

## by 司徒正美
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();
}
}

注意

除了新的createRef API外,回撥refs將繼續得到支援。

您不需要在元件中替換回撥refs。它們稍微靈活一些,因此它們將繼續作為一個高階特性。

forwardRef API

高階元件(或HOCs)是在元件之間重用程式碼的常用方法。基於上面的主題上下文示例,我們可能會建立一個臨時物件,將當前的“主題”作為一個屬性注入:

## by 司徒正美
function withTheme(Component) {
return function ThemedComponent(props) {
return (
<ThemeContext.Consumer>
{theme => <Component {...props} theme={theme} />}
</ThemeContext.Consumer>
);
};
}

我們可以使用上述特殊的方式將元件連線到主題上下文,而不必直接使用主題上下文。例如:

## by 司徒正美
class FancyButton extends React.Component {
buttonRef = React.createRef();
focus() {
this.buttonRef.current.focus();
}
render() {
const {label, theme, ...rest} = this.props;
return (
<button
{...rest}
className={`${theme}-button`}
ref={this.buttonRef}>
{label}
</button>
);
}
}
const FancyThemedButton = withTheme(FancyButton);
// We can render FancyThemedButton as if it were a FancyButton
// It will automatically receive the current "theme",
// And the HOC will pass through our other props.
<FancyThemedButton
label="Click me!"
onClick={handleClick}
/>;

HOCs通常會將props傳遞給它們包裝的元件。不幸的是,refs沒有衝透進去。這意味著如果我們使用FancyThemedButton,我們就不能將ref新增到FancyButton中,因此我們無法呼叫focus()。

新的代理API通過提供一種方法來攔截一個ref,並將其轉發為一個普通的props,從而解決了這個問題:

## by 司徒正美
function withTheme(Component) {
// Note the second param "ref" provided by React.forwardRef.
// We can attach this to Component directly.
function ThemedComponent(props, ref) {
return (
<ThemeContext.Consumer>
{theme => (
<Component {...props} ref={ref} theme={theme} />
)}
</ThemeContext.Consumer>
);
}
// These next lines are not necessary,
// But they do give the component a better display name in DevTools,
// e.g. "ForwardRef(withTheme(MyComponent))"
const name = Component.displayName || Component.name;
ThemedComponent.displayName = `withTheme(${name})`;
// Tell React to pass the "ref" to ThemedComponent.
return React.forwardRef(ThemedComponent);
}
const fancyButtonRef = React.createRef();
// fancyButtonRef will now point to FancyButton
<FancyThemedButton
label="Click me!"
onClick={handleClick}
ref={fancyButtonRef}
/>;

元件生命週期鉤子的變化

React的類元件API已經存在多年,幾乎沒有變化。但是,當我們為更高階的特性(例如錯誤邊界和即將到來的非同步渲染模式)新增支援時,我們以它本來沒有打算的方式來擴充套件這個模型。

例如,在當前的API中,用一些非尋常的手段來阻止初始渲染是很容易的。在某種程度上,這是因為有太多的鉤子來完成這項既定的任務,而且還不清楚哪一個是最好的。我們已經注意到錯誤處理的中斷行為通常不會被考慮,並且可能導致記憶體洩漏(這也會影響即將到來的非同步渲染模式)。當前的類元件API也使其他的工作變得複雜,比如我們的程式碼優化器(Prepack)的工作。

componentWillMount, componentWillReceiveProps, componentWillUpdate這些鉤子很容易引發問題,並且也嚴重擾亂React的生命週期。基於這些原因,我們將廢棄這些方法,以支援更好的替代方案。

我們認識到這一變化將影響許多現有的元件。因此,遷移路徑將儘可能平緩,並提供遷移方案。(在Facebook,我們擁有5萬多個React元件。我們也依賴於一個漸進的釋出週期!

注意

棄用警告將在React16以後的版本中啟用, 一直保留到17釋出時。

即使在React17中,仍然可以使用它們,但是它們將新增“UNSAFE_”字首,以表明它們可能導致問題。我們還準備了一個自動化的指令碼,以便現有程式碼中重新命名它們。

除了廢棄不安全的生命週期鉤子外,我們還增加了一些新的生命週期鉤子:

getDerivedStateFromProps 用來componentWillReceiveProps。

getSnapshotBeforeUpdate,用在更新前從DOM中安全地讀取屬性。

StrictMode 元件

<StrictMode />是一種專門用於暴露潛在問題的工具。與<Fragment />一樣,<StrictMode/>將 不會渲染到檢視中。它能為其子元件啟用額外的檢查和警告。

注意

<StrictMode />檢查只在開發模式下執行;它們不會影響生產構建。

雖然嚴格的模式不可能捕獲所有的問題(例如某些型別的竄改),但它可以幫助很多人。如果您在嚴格的模式下看到警告,這些事情很可能會導致非同步渲染的錯誤。

在16.3版本中,StrictMode幫助:

  1. 識別具有不安全生命週期鉤子的元件。
  2. 關於遺留字串ref API用法的警告。
  3. 檢測意想不到的副作用

相關文章

IOS開發 最新文章