React 16 新特性

來源:互聯網
上載者:User

2017年9月26日React 16發布,通過官網和樣本瞭解一下新特性。 React 16更新 新js環境要求

react16依靠Map和Set集合和requestAnimationFrame(一個針對動畫效果的API)
新功能
- Fragments:render函數可以返回數組和字串- error boundaries:錯誤處理- portals :支援聲明性地將子樹渲染到另一個DOM節點- custom DOM attributes :ReactDom允許傳遞非標準屬性- improved server-side rendering:提升服務端渲染效能

Fragments

render() {  return [    <li key="A"/>First item</li>,    <li key="B"/>Second item</li>,    <li key="C"/>Third item</li>,  ];}

詳見API

error boundaries

之前,一旦某個組件發生錯誤,整個組件樹將會從根節點被unmount下來。React 16修複了這一點,引入了Error Boundary的概念,中文譯為“錯誤邊界”,當某個組件發生錯誤時,我們可以通過Error Boundary捕獲到錯誤並對錯誤做優雅處理,如使用Error Boundary提供的內容替代錯誤組件。Error Boundary可以看作是一種特殊的React組件,新增了componentDidCatch這個生命週期函數,它可以捕獲自身及子樹上的錯誤並對錯誤做優雅處理,包括上報錯誤記錄檔、展示出錯提示,而不是卸載整個組件樹。(註:它並不能捕獲runtime所有的錯誤,比如組件回調事件裡的錯誤,可以把它想象成傳統的try-catch語句)

實踐:

抽象出檢查錯誤邊界公用組件:

class ErrorBoundary extends React.Component{    constructor(props){        super(props);        this.state=({            ifError:false        });    }    componentDidCatch(err, info) {        this.setState({ ifError: true })        console.log(err);    }    render(){        if(this.state.ifError){            return `this or its children has error`;        }        return this.props.children    }}

建立一個簡單的包含錯誤的子組件:

class ErrorComponent extends React.Component{    render(){        const str = '123';        return str.toFixed(2);    }}

使用錯誤邊界組件包裹可能出錯的組件

class MainShowComponent extends React.Component{    render(){        return (            <div>                <ErrorBoundary>                    <ErrorComponent/>                </ErrorBoundary>            </div>        )    }}

當被錯誤邊界組件包裹的子組件中出現錯誤,會將錯誤組件替換為字串:this or its children has error,而不會導致整體組件樹被卸載。

Portals

Portals提供了一種一流的方法來將子代呈現到父組件的DOM階層之外的DOM節點。

ReactDOM.createPortal(  child,  container);

第一個參數(child)是任何可渲染的React子項目,如元素,字串或片段。第二個參數(container)是一個DOM元素。

通常,當您從組件的render方法返回一個元素時,它將作為最近的父節點的子項目裝載到DOM中:

render() {  // React mounts a new div and renders the children into it  return (    <div>      {this.props.children}    </div>  );}

但是,有時將子項插入到DOM中的其他位置會很有用:

render() {  // React does *not* create a new div. It renders the children into `divNode`.  // `divNode` is any valid DOM node, regardless of its location in the DOM.  return React.createPortal(    this.props.children,    divNode,  );}

有關Portals 和其事件冒泡詳見官網和CodePen例子

custom DOM attributes

支援非標準的自訂DOM屬性,在之前的版本中,React會忽略無法識別的HTML和SVG屬性,自訂屬性只能通過data-*形式添加,現在它會把這些屬性直接傳遞給DOM,這個改動讓React可以去掉屬性白名單,從而減少了檔案大小。但當DOM傳遞的自訂屬性是函數類型或event handler類型時,也會被React忽略掉。

<div a={()=>{}}></div>   //錯誤

improved server-side rendering

提升服務端渲染效能,React 16的SSR被完全重寫,新的實現非常快,接近3倍效能於React 15,現在提供一種流模式streaming,可以更快地把渲染的位元組發送到用戶端。 打破改變

調度和生命週期的改變 ReactDOM.render()和ReactDom.unstable_renderIntoContainer()如果在生命週期函數中調用將會返回null。所以解決此類問題可以使用portals或者refs

setState的改變:

調用setState返回null將不會更新render,這樣可以讓你在更新方法中自己決定是否更新。

this.setState(    (state)=>{        if(state.curCount%2 === 0){            return {curCount:state.curCount+1}        }else{            return null;        }    })

在render方法中調用setState總是會導致更新,之前版本不支援,但盡量不要在render中調用setState。

setState的回呼函數會在componentDidMount/ componentDidUpdate 執行之後立即執行,而不是在所有組件渲染之後。

    this.setState(        (state)=>{            if(state.curCount%2 === 0){                return {curCount:state.curCount+1}            }else{                return null;            }        },        ()=>{            console.log(this.state.curCount);        }    )

當兩個組件<A /> 和 <B / >發生替換時,B.componentWillMount總是會在A.componentWillUnmount之前執行,而在之前,A.componentWillUnmount有可能會提前執行。 之前版本,當改變一個組件的ref時,ref和dom會在組件的render方法被調用之前分離。現在,我們延遲了ref的改變,直到dom元素被改變了,ref才會和dom分離。

對於不使用React而是使用其他方法來重新渲染容器是不安全的。這在以前的版本中也許會生效,但是我們覺得不支援這樣做。現在對於這種情況我們會發出一個警告,而且你需要使用ReactDOM.unmountComponentAtNode來清空你的節點樹。

ReactDOM.render(<App />, div);div.innerHTML = 'nope';ReactDOM.render(<App />, div);//渲染一些沒有被正確清理的東西

而你需要:

ReactDOM.render(<App />, div);ReactDOM.unmountComponentAtNode(div);div.innerHTML = 'nope';ReactDOM.render(<App />, div); // Now it's okay

查看此issue

componentDidUpdate生命週期不再接受prevContext參數。 使用不唯一的key可能會導致子組件的複製或者遺失,使用不唯一的key並不支援,並且也從未支援,但之前這是一個硬性錯誤。 Shallow renderer(淺層渲染)不再觸發componentDidUpdate(),因為DOM的refs是停用。這也使得它與componentDidMount()之前版本中的調用一致。 Shallow renderer不再支援unstable_batchedUpdates()。 ReactDOM.unstable_batchedUpdates 現在回調之後只有一個額外的參數。

單檔案瀏覽器版本的名稱和路徑已經改變,以強調開發和生產版本之間的差異 react/dist/react.js → react/umd/react.development.js react/dist/react.min.js → react/umd/react.production.min.js react-dom/dist/react-dom.js → react-dom/umd/react-dom.development.js react-dom/dist/react-dom.min.js → react-dom/umd/react-dom.production.min.js

重寫並改進伺服器渲染器 伺服器渲染不再使用標記驗證,而是儘力附加到現有的DOM,警告不一致。它也不再使用每個節點上的空白組件和資料反饋屬性的注釋。 為伺服器渲染容器現在有一個明確的API。使用ReactDOM.hydrate而不是ReactDOM.render如果你正在恢複伺服器呈現的HTML。繼續使用,ReactDOM.render如果你只是做用戶端渲染。

當未知的屬性傳遞給DOM組件時,如果是有效值,React會渲染進DOM。查看文檔 在render和生命週期函數中的錯誤預設會卸載整個DOM樹,為了阻止這個,可以在UI的相應位置添加錯誤邊界。 棄用 不再構建react-with-addons.js,所有相容的外掛程式都是在npm上單獨發布的,如果你需要它們,可以使用單檔案瀏覽器版本。 在15.x版本中的棄用已經從核心包中刪除,React.createClass現在可以作為 create-react-class,React.PropTypes可以作為prop-types,React.DOM 作為 react-dom-factories,react-addons-test-utils 作為 react-dom/test-utils使用, shallow renderer 作為 react-test-renderer/shallow使用。參閱15.5.0和15.6.0文檔參考。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.