React 16.6 釋出,一大波新功帶你看未來的 React 開發方式

Jokcy發表於2018-10-29

最近(2018-10-23)React官方釋出了16.6版本,開放了一堆新的功能,而這其中的一些新功能,代表這未來的React開發方式,讓我們來一起窺探未來吧。

lazy

最讓人期待的功能肯定就是lazy功能了,配合釋出了一個Suspense元件,也就是最開始命名為Placeholder的元件,用來配合render方法內部的非同步操作的,讓我們先來看一下lazy的用法

import React, {lazy, Suspense} from 'react';
const OtherComponent = lazy(() => import('./OtherComponent'));

function MyComponent() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <OtherComponent />
    </Suspense>
  );
}
複製程式碼

做過code-splitting的同學能聞到熟悉的味道。以前我們要用第三方包或者自己處理非同步過程,現在,React原生支援啦,而且你可以把非同步的過程直接扔到render方法裡面,就跟寫普通元件一樣,而且可以方便得通過Suspense元件來提供fallback

然而這並不僅僅Suspense的唯一用處,事實上這次React正式開放Suspense元件代表著所有非同步的操作都可以在render方法裡面做了,其實我很意外,我以為正式開放肯定要等到17版本

那麼非同步操作還能做啥?如果同學們看過年初Dan在冰島的分享,應該就知道,Suspense能夠讓我們載入資料的操作變得異常簡單。沒看過的同學可以看這裡,現在npm上也有一個包提供資料載入的功能了,simple-cache-provider,但是現在還不要在正式環境使用他哦。

關於這部分如何實現的,我會在之後的原始碼分析上詳細講解,有興趣的同學可以關注我。

React.memo

ClassComponent可以通過繼承類PureComponent或者實現shouldComponentUpdate來主動判斷元件是否需要重新渲染,以此來提高效能,但是FunctionalComponent到目前為止沒有類似的功能。

所以今天React釋出了React.memo方法,來實現類似PureComponent的功能,即淺比較props是否有變化,如果沒有變化,就不重新渲染當前元件

const FunctionalComponent = React.memo((props) => {
  // only render if props change
})
複製程式碼

static contextType

在React16.3中提供了我們一個標準的用於替代老的context的API,也就是React.createContext,然後通過context.Providercontext.Consumer來傳遞值,這種方式消除了老的context API效能低下的問題,這個問題我在之前也有詳細分析,感興趣的同學可以看這裡,而且老的API程式碼量很多,所以下個大版本React會移除老的API。

但是在讓生態外掛升級到新的API的過程中,有人提出在ClassComponent中用新的API很麻煩(???沒感覺啊),所以React提供了一種在ClassComponent中使用新API的方法

import React, { Component } from 'react';

const context = React.createContext('defaultValue')


const ProviderComp = ({ children }) => (
  <context.Provider value="provider">
    {children}
  </context.Provider>
)

class ConsumerComp extends Component {
  static contextType = context

  componentDidMount() {
    console.log(this.context)
  }

  render() {
    return (
      <p>{this.context}</p>
    )
  }
}

class App extends Component {
  render() {
    return (
      <ProviderComp>
        <ConsumerComp />
      </ProviderComp>
    );
  }
}
複製程式碼

通過宣告static contextType = context,讓ClassComponent可以訂閱最近的一個context provider注意這裡contextType是固定宣告,換成別的名字都不行。如果ConsumerComp不在Provider的子樹中,那麼會使用defaultValue

class App extends Component {
  render() {
    return (
      <>
        <ProviderComp />
        <ConsumerComp />  // show default value
      </>
    );
  }
}
複製程式碼

這也是為了提高React的整體效能,移除老舊API做努力。

static getDerivedStateFromError()

在釋出Error Boundaries的時候,React提供了一個新的生命週期方法componentDidCatch,在捕獲到錯誤的時候會觸發,你可以在裡面修改state以顯示錯誤提醒的UI,或者將錯誤資訊傳送給服務端進行log用於後期分析。但是這裡有個問題,就是在捕獲到錯誤的瞬間,React會在這次渲染週期中將這個元件渲染為null,這就有可能導致他的父元件設定他上面的ref獲得null而導致一些問題,所以現在提供了這個方法。

這個方法跟getDerivedStateFromProps類似,唯一的區別是他只有在出現錯誤的時候才觸發,他相對於componentDidCatch的優勢是在當前的渲染週期中就可以修改state,以在當前渲染就可以出現錯誤的UI,而不需要一個null的中間態。

而這個方法的出現,也意味著以後出現錯誤的時候,修改state應該放在這裡去做,而後續收集錯誤資訊之類的放到componentDidCatch裡面。

StrictMode下的新提醒

StrictMode是用來提醒開發者用了即將被廢棄的API的,像componentWillMount這些宣告週期都會提醒,這次新加了兩個API的提醒,ReactDOM.findDOMNode(),和老的context api

也代表著這兩個下個大版本肯定會被移除。所以兄弟們還不趕緊更新!

我是Jocky,一個專注於React技巧和深度分析的前端工程師,React絕對是一個越深入學習,越能讓你覺得他的設計精巧,思想超前的框架。關注我獲取最新的React動態,以及最深度的React學習。更多的文章看這裡

相關文章