摘要:譯者前端小智原文就像人們對更新移動應用程序和操作系統感到興奮一樣,開發人員也應該對更新框架感到興奮。錯誤邊界是一種組件。注意將作為值傳遞進去并不會導致使用。如果兩者不同,則返回一個用于更新狀態的對象,否則就返回,表示不需要更新狀態。
譯者:前端小智
原文:medium.freecodecamp.org/why-react16…
就像人們對更新移動應用程序和操作系統感到興奮一樣,開發人員也應該對更新框架感到興奮。不同框架的新版本具有新特性和開箱即用的技巧。
下面是將現有應用程序從 React 15 遷移到 React 16 時應該考慮的一些好特性。
想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等著你!
錯誤處理React 16 引入了錯誤邊界的新概念。
現在在React 16中,大家就能使用錯誤邊界功能,而不用一發生錯誤就解除整個程序掛載了。把錯誤邊界看成是一種類似于編程中try-catch語句的機制,只不過是由 React 組件來實現的。
錯誤邊界是一種React組件。它及其子組件形成一個樹型結構,能捕獲JavaScript中所有位置的錯誤,記錄下錯誤,并且還能顯示一個后備界面,避免讓用戶直接看到組件樹的崩潰信息。
這里涉及到一種新的生命周期函數叫componentDidCatch(error, info)。無論什么樣的類組件,只要定義了這個函數,就成為了一個錯誤邊界。
class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } componentDidCatch(error, info) { // Display fallback UI this.setState({ hasError: true }); // 你還可以將錯誤記錄到錯誤報告服務中 logErrorToMyService(error, info); } render() { if (this.state.hasError) { // 可以渲染任何自定義回退界面 returnSomething went wrong.
; } return this.props.children; } }
也可以將其用作常規組件使用:
componentDidCatch() 方法的工作原理類似于JavaScript catch{}塊,但它適用于組件。只有類組件可以是錯誤邊界。實際上,在大多數情況下,你都希望聲明一次錯誤邊界組件,然后在整個應用程序中使用它。
請注意,錯誤邊界只會捕獲位于它們之下的組件中的錯誤。錯誤邊界無法捕獲到自身的錯誤。如果錯誤邊界渲染錯誤消息失敗,錯誤將被傳播到上方最接近的錯誤邊界。這也類似于 JavaScript 中的 catch{}塊。
有了錯誤邊界,即使某個組件的結果有錯誤,整個React程序掛載也不會被解除。只有出錯的那個組件會顯示一個后備界面,而整個程序仍然完全正常運行。
點擊查看在線事例
關于錯誤邊界更多的內容可查看官網。
新的 render 返回類型:片段和字符串現在,在渲染時可以擺脫將組件包裝在 div 中。
你現在可以從組件的 render 方法返回元素數組。與其他數組一樣,你需要為每個元素添加一個鍵以避免發出鍵警告:
render() { // No need to wrap list items in an extra element! return [ // Don"t forget the keys :)
從React 16.2.0開始,它支持JSX的一個特殊片段語法,該語法不需要鍵。
render() { return ( <>> ); }
支持返回字符串:
render() { return "Look ma, no spans!"; }Portal
Portal 提供了一種將子節點渲染到父節點之外的 dom 節點。
ReactDOM.createPortal(child, container)
第一個參數 (child)是任何可渲染的 React子元素,例如元素,字符串或片段。 第二個參數 (container) 是 DOM 元素。
在 React15.X 版本中,我們只能講子節點在父節點中渲染,基本用法如下:
render() { // React需要創建一個新的div來包含子節點 return ({this.props.children}); }
但是如果需要將子節點插入到父節點之外的dom呢,React15.x 及之前都沒有提供這個功能的 API。 可以使用 React16.0 中的 portal:
render() { // React不需要創建一個新的div去包含子元素,直接將子元素渲染到另一個 //dom節點中 //這個dom節點可以是任何有效的dom節點,無論其所處于dom樹中的哪個位置 return ReactDOM.createPortal( this.props.children, domNode, ); }
Portal 的一個典型用例是這樣的:當父組件帶有 overflow:hidden 或 z-index 樣式時,你希望子組件在視覺上能夠“突破”它的容器。例如,對話框、懸停卡和工具提示。
點擊查看在線事例
自定義 DOM 屬性
React15 會忽略任何未知的 DOM 屬性。React 會跳過它們,因為無法識別它們。
// 你的代碼
React 15 將渲染一個空的 div:
// React 15 output:
在 React16 中,輸出將如下所示(會顯示自定義屬性,并且完全不會被忽略)
// React 16 output:在 state 中設置 null 避免重新渲染
有時候我們需要通過函數來判斷組件狀態更新是否觸發重新渲染,在 React 16 中,我們可以通過調用 setState 時傳入 null 來避免組件重新渲染,這也就意味著,我們可以在 setState 方法內部決定我們的狀態是否需要更新,
const MAX_PIZZAS = 20; function addAnotherPizza(state, props) { // Stop updates and re-renders if I"ve had enough pizzas. if (state.pizza === MAX_PIZZAS) { return null; } // If not, keep the pizzas coming! :D return { pizza: state.pizza + 1, } } this.setState(addAnotherPizza);
更多相關信息請閱讀這里
創建 ref現在使用 React16 創建refs要容易得多。 為什么需要使用refs:
管理焦點、文本選擇或媒體播放。
觸發動畫。
與第三方 DOM 庫集成。
ref 是使用 React.createRef() 創建的,并通過 ref 屬性附加到 React 元素。ref 通常是在構造組件時被分配給實例的屬性,以便在整個組件中引用它們。
class MyComponent extends React.Component { constructor(props) { super(props); this.myRef = React.createRef(); } render () { return } }
上述是創建Ref指向的方法, 在Ref 所指向的組件,在render后就可以調用,React16.3 中提供了current 屬性,用于引用render后的節點:
componentDidMount(){ console.log(this.myRef.current); //render之后就可以輸出該ref指向的那個節點 }
此外,同樣的 Ref 所指向的節點可以是 dom 節點,也可以是類組件。
Ref 的值因節點的類型不同而有所不同:
當 ref 屬性用于 HTML 元素時,在構造函數中使用 React.createRef() 創建的 ref 將底層 DOM 元素作為 current 屬性。
當 ref 屬性用于自定義類組件時,ref 對象將已掛載的組件實例作為 current 屬性。
你可能不會在函數組件上使用 ref 屬性,因為它們沒有實例。
Context APIContext 提供了一種通過組件樹傳遞數據的方法,無需在每一層手動傳遞 prop。
const { Provider, Consumer } = React.createContext(defaultValue)
創建{Provider,Consumer}對。當 React 渲染 Consumer 時,它將從樹中最接近的 Provider 讀取當前上下文值。
defaultValue 參數只在消費者在樹中找不到匹配的 Provider 時才會用到,這在多帶帶測試組件時十分有用。注意:將 undefined 作為 Provider 值傳遞進去并不會導致 Consumer 使用 defaultValue。
一個允許 Consumer 訂閱上下文變更的 React 組件。
一個 Provider 可以連接多個 Consumer,可以在樹中嵌套 Provider,實現更深的值覆蓋。
{value => /* render something based on the context value */}
訂閱上下文更改的 React 組件。
需要一個函數作為子組件。這個函數接收當前上下文值,并返回一個 React 節點。傳給函數的 value 參數將等于樹中最近的 Provider 的 value。如果沒有匹配的 Provider,則 value 參數將等于傳給 createContext() 的 defaultValue。
static getDerivedStateFromProps()在很長一段時間內,componentWillReceiveProps是在沒有附加渲染的情況下更新狀態的唯一方法。
在版本16.3中,我們引入了一個全新的生命周期函數getDerivedStateFromProps用來替換componentWillReceiveProps,并用更安全的方式處理相同的場景。
與此同時,我們意識到人們對如何使用這兩種方法有很多誤解,我們發現了一些反模式,這些錯誤導致了微妙而令人困惑的bug。
在16.4中,有關getDerivedStateFromProps的修復使得派生狀態更加可預測,因此錯誤使用的結果更容易被注意到。
getDerivedStateFromProps 會在調用 render 方法之前被調用,它應該返回一個用于更新狀態的對象,或者如果不更新任何狀態就返回 null。
這個方法適用于一些罕見的用例,其中 state 依賴 prop 的變化。例如,可以很方便地實現一個
衍生 state 會導致冗長的代碼,并讓你的組件難以開發和維護。
你可以考慮更簡單的替代方案:
如果你需要在 prop 發生變更時做一些其他事情(例如數據提取或動畫),請改用 componentDidUpdate 生命周期。
如果你只想在 prop 發生變更時重新計算某些數據,請改用 memoization helper:
*?如果你想在 prop 發生變更時“重置”某個狀態,請考慮創建受控組件或帶有鍵的非受控組件。
此方法無權訪問組件實例。 如果你愿意,可以通過提取組件props的純函數和類定義之外的狀態,在getDerivedStateFromProps() 和其他類方法之間重用一些代碼。
注意,不管怎樣,這個方法都會在每次進行渲染時觸發。這與 UNSAFE_componentWillReceiveProps 完全相反。它只在父組件進行重新渲染時觸發,而且不作為本地 setState 的結果。
將nextProps.someValue與this.props.someValue進行比較。 如果兩者都不同,那么我們執行一些操作:
static getDerivedStateFromProps(nextProps, prevState){ if(nextProps.someValue!==prevState.someValue){ return { someState: nextProps.someValue}; } return null }
它接收兩個參數 nextProps 和 prevState。如前所述,你無法在這個方法中訪問 this。你必須將 prop 存儲在 state 中,然后將 nextProps 與之前的 prop 進行對比。在上面的代碼中,nextProps 和 prevState 進行了比較。如果兩者不同,則返回一個用于更新狀態的對象,否則就返回 null,表示不需要更新狀態。如果 state 發生變更,就會調用 componentDidUpdate,我們可以像在 componentWillReceiveProps 中那樣執行所需的操作。
React 生命周期事件
react v16.3,最大的變動莫過于生命周期去掉了以下三個:
componentWillMount
componentWillReceiveProps
componentWillUpdate
同時為了彌補失去上面三個周期的不足又加了兩個:
static getDerivedStateFromProps
getSnapshotBeforeUpdate
舊的生命周期十分完整,基本可以捕捉到組件更新的每一個state/props/ref,沒有什從邏輯上的毛病。
但是架不住官方自己搞事情,react打算在17版本推出新的Async Rendering,提出一種可被打斷的生命周期,而可以被打斷的階段正是實際dom掛載之前的虛擬dom構建階段,也就是要被去掉的三個生命周期。
生命周期一旦被打斷,下次恢復的時候又會再跑一次之前的生命周期,因此componentWillMount,componentWillReceiveProps, componentWillUpdate?都不能保證只在掛載/拿到props/狀態變化的時候刷新一次了,所以這三個方法被標記為不安全。
你的點贊是我持續分享好東西的動力,歡迎點贊!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/7322.html
摘要:就像人們對更新移動應用程序和操作系統感到興奮一樣,開發人員也應該對更新框架感到興奮。錯誤邊界是一種組件。注意將作為值傳遞進去并不會導致使用。如果兩者不同,則返回一個用于更新狀態的對象,否則就返回,表示不需要更新狀態。 就像人們對更新移動應用程序和操作系統感到興奮一樣,開發人員也應該對更新框架感到興奮。不同框架的新版本具有新特性和開箱即用的技巧。 下面是將現有應用程序從 React 15...
摘要:更新日志應對添加以編程方式收集性能測量。在和在將棄用為常見攻擊面。添加對事件的支持。在從調用時發出警告,創建循環。在和從錯誤的渲染器使用時發出警告。 2019年8月8日,我們發布了React 16.9。它包含幾個新功能,錯誤修正和新的棄用警告,以幫助準備未來的主要版本。 showImg(https://segmentfault.com/img/bVbwoB5?w=1728&h=666)...
摘要:更新日志應對添加以編程方式收集性能測量。在和在將棄用為常見攻擊面。添加對事件的支持。在從調用時發出警告,創建循環。在和從錯誤的渲染器使用時發出警告。 2019年8月8日,我們發布了React 16.9。它包含幾個新功能,錯誤修正和新的棄用警告,以幫助準備未來的主要版本。 showImg(https://segmentfault.com/img/bVbwoB5?w=1728&h=666)...
摘要:弄了一個持續更新的筆記,可以去看看,鏈接地址此篇文章的地址使用兩年后值得嗎基礎筆記的地址可以也可以。使用,你可以使用抽象類等功能。有關抽象類的更多信息支持,和方法,只讀屬性。 弄了一個持續更新的github筆記,可以去看看,鏈接地址:Front-End-Basics 此篇文章的地址:使用TypeScript兩年后-值得嗎? 基礎筆記的github地址:https://githu...
閱讀 1261·2019-08-30 12:49
閱讀 3101·2019-08-28 18:14
閱讀 813·2019-08-26 11:38
閱讀 1669·2019-08-23 18:23
閱讀 2819·2019-08-23 17:04
閱讀 490·2019-08-23 16:52
閱讀 4001·2019-08-23 16:43
閱讀 2762·2019-08-23 16:12