React 頂層 API
React
是 React 函式庫的進入點。 如果你使用 <script>
標籤載入 React,這些頂層 API 可以在 React
全域變數使用。如果你使用 ES6 撰寫並使用 npm,你可以寫成 import React from 'react'
。如果你使用 ES5 撰寫並使用 npm,你可以寫成 var React = require('react')
。
概觀
Component
React component 可以讓你把 UI 切分為獨立並可重複使用的單位,並且每個單位可以抽出來獨立思考。React component 可以透過繼承 React.Component
或是 React.PureComponent
定義。
如果你沒有使用 ES6 class,你可以使用 create-react-class
模組。請參閱使用 React 但不使用 ES6 取得更多資訊。
React component 也可以定義為 function 並可以被封裝:
建立 React Element
我們推薦使用 JSX 來描述你的 UI 應該長成什麼樣子。 每個 JSX element 都只是呼叫 React.createElement()
的語法糖。當你使用 JSX 的時候你將不需要直接呼叫以下的 method:
參閱使用 React 但不使用 JSX 取得更多資訊。
操作 Element
React
提供了多種 API 讓你可以操作 element:
Fragment
React
也提供了一個 component 讓你一次 render 多個 element 而不需要額外的 wrapper。
Refs
Suspense
Suspense 讓 components 在 render 之前可以「暫停」並等待其他事情。目前 Suspense 只支援一個情境:使用 React.lazy
動態載入 component 。在未來,我們也會支援像是抓取資料等更多的使用情境。
Hooks
Hooks 是 React 16.8 開始的新功能。這讓你可以使用 state 以及其他的 React 功能而不需要撰寫一個 class。Hooks 有一個專屬的文件專區 和分開的 API 參考資料:
參考資料
React.Component
React.Component
是當你使用 ES6 classes 定義 React component 時所用的 base class:
class Greeting extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
參閱 React.Component API 參考資料 可查到跟 React.Component
相關的 method 及 properties。
React.PureComponent
React.PureComponent
跟 React.Component
很相似。他們之間的差別是 React.Component
並沒有實作 shouldComponentUpdate()
,但 React.PureComponent
提供了一個實作以對於 prop 及 state 進行 shallow compare。
備註
React.PureComponent
的shouldComponentUpdate()
只對 object 進行 shallow compare。如果這些 object 包含複雜的資料結構,在深層的資料有所改變的時候將有可能回傳錯誤結果 (false-negative)。繼承PureComponent
的時候,請確保你只有簡單的 prop 跟 state,或在當你知道深層的資料有所改變的時候使用forceUpdate()
。你也可以考慮改用 immutable object 進行快速的深層資料比較。此外,
React.PureComponent
的shouldComponentUpdate()
將會跳過整個 subtree 的 prop 更新。請確保所有 children component 也是「pure」的。
React.memo
const MyComponent = React.memo(function MyComponent(props) {
/* render using props */
});
React.memo
是一個 higher order component。
如果你的 function component 每次得到相同 prop 的時候都會 render 相同結果,你可以將其包在 React.memo
之中,透過快取 render 結果來在某些情況下加速。這表示 React 會跳過 render 這個 component,並直接重用上次的 render 結果。
React.memo
只會確認 props 的改變。如果你的 function component 被 wrap 在 React.memo
內,實作中具有一個 useState
、useReducer
或 useContext
Hook,當 state 或 context 改變時,它仍然會持續 rerender。
這預設只會對 prop 進行 shallow compare 。如果你需要控制比較的方法,你可以提供一個自訂的比較 function 作為第二個參數。
function MyComponent(props) {
/* render using props */
}
function areEqual(prevProps, nextProps) {
/*
return true if passing nextProps to render would return
the same result as passing prevProps to render,
otherwise return false
*/
}
export default React.memo(MyComponent, areEqual);
這個 function 是用來作為效能最佳化所用。請勿依賴這個 function 來「避免」render,這可能會產生 bug。
備註
與 class component 的
shouldComponentUpdate()
method 不同,areEqual
function 當 prop 相等的時候回傳true
,不相等的時候回傳false
。 這跟shouldComponentUpdate
剛好相反。
createElement()
React.createElement(
type,
[props],
[...children]
)
建立並回傳一個新的 React element 描述指定的 type。 Type 參數可以是一個標籤名稱字串(像是 'div'
或是 'span'
)、一個 React component type (class 或是 function) 或者是一個 React fragment type。
使用 JSX 寫的程式將會被轉換使用 React.createElement()
。如果使用 JSX,你通常不需要自己呼叫 React.createElement()
。請參閱使用 React 但不使用 JSX。
cloneElement()
React.cloneElement(
element,
[props],
[...children]
)
複製並回傳一個基於 element
的新 React element。這個回傳的 element 的 prop 將會是原本 element 的 prop 與新的 prop 進行 shallow 合併之後的結果。新的 children 將會取代原先的 children。 原先 element 的 key
與 ref
將會被保留。
React.cloneElement()
幾乎等於:
<element.type {...element.props} {...props}>{children}</element.type>
但是,這同時也會保留 ref
。如果你有一個 child 上有 ref
的時候,你將不會不小心從你的上層元件偷走 ref。你的新 element 會保留一樣的 ref
。
這個 API 是用來取代目前已經過時的 React.addons.cloneWithProps()
。
createFactory()
React.createFactory(type)
回傳一個 function 可以產生指定 type 的 React element。跟 React.createElement()
一樣,這個 type 參數可以是一個標籤名稱字串(像是 'div'
或是 'span'
)、一個 React component type (class 或是 function) 或者是一個 React fragment type。
這個 helper 已經被認定為過時,我們建議你使用 JSX 或是直接使用 React.createElement()
。
如果使用 JSX,你通常不需要自己呼叫 React.createFactory()
。請參閱使用 React 但不使用 JSX。
isValidElement()
React.isValidElement(object)
檢查一個 object 是否為 React element。通常回傳 true
或是 false
。
React.Children
React.Children
提供了一些工具可以將 this.props.children
作為不透明的資料結構處理。
React.Children.map
React.Children.map(children, function[(thisArg)])
對每一個列為 children
之中的直接 child 呼叫 function 並將 this
設定為 thisArg
。如果 children
是一個 array,這將會列舉整個 array 並對每一個 child 呼叫這個 function。如果 children 是 null
或是 undefined
,這個 method 將會回傳 null
或是 undefined
而不是一個 array。
備註
如果
children
是一個Fragment
,它將會被視為只有一個 child 而不會繼續深入列舉。
React.Children.forEach
React.Children.forEach(children, function[(thisArg)])
跟 React.Children.map()
一樣,但不會回傳一個 array 。
React.Children.count
React.Children.count(children)
回傳 children
到底有幾個 child,跟傳入 map
或是 forEach
的 callback 會被呼叫的次數一致。
React.Children.only
React.Children.only(children)
確認 children
只有一個 child (一個 React element)並回傳它,不然這個 method 將會拋出錯誤。
備註
React.Children.only()
無法接受React.Children.map()
的回傳值,因為那個回傳值將會是一個 array 而不是一個 React element 。
React.Children.toArray
React.Children.toArray(children)
將 children
這個不透明的資料結構轉為一個扁平的 array 並對每個 child 指定一個 key。如果你想要在你的 render method 中操作 children 的集合時非常有用,特別是當你想要在傳遞它們之前調整順序或是擷取一部份 this.props.children
的時候。
備註
React.Children.toArray()
會改變 key 來保留巢狀 array 的語意。也就是說toArray
將會在每個 key 前面加入前綴,確保每個 element 的 key 都在與它原本輸入的 array 相關。
React.Fragment
React.Fragment
讓你可以在一個 render()
method 中一次回傳多個 element 而不需要建立一個額外的 DOM element:
render() {
return (
<React.Fragment>
Some text.
<h2>A heading</h2>
</React.Fragment>
);
}
你也可以使用 <></>
的精簡表示法。請參閱 React v16.2.0: 更好的 Fragment 支援以獲得更多資訊。
React.createRef
React.createRef
會建立一個 ref 以透過 ref attribute 夾帶在一個 React element 之上。
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(); }
}
React.forwardRef
React.forwardRef
會建立一個 React component 並將 ref attribute 轉交給旗下的另外一個 component 。這個技巧不是很常被使用,但在以下兩個情況很適合:
React.forwardRef
接受一個 render function 作為參數。React 會呼叫這個 function 並傳入兩個參數: props
以及 ref
。這個 function 應該要回傳一個 React node。
const FancyButton = React.forwardRef((props, ref) => ( <button ref={ref} className="FancyButton"> {props.children}
</button>
));
// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;
在上面這個範例,React 會把給予 <FancyButton ref={ref}>
的 ref
轉交給傳入 React.forwardRef
的 function 作為其第二個參數。這個 render function 接著將這個 ref
轉交給 <button ref={ref}>
element。
結果,當 React 夾上這個 ref 的時候,ref.current
將會直接指到 <button>
這個 DOM element 實例。
請參閱轉交 ref 獲得更多資訊。
React.lazy
React.lazy()
讓你可以定義一個動態載入的 component。這可以在初始 render 期間延緩載入沒有被用到的 component 來減少 bundle size。
你可以閱讀我們的 code splitting 文件 來學習怎麼使用它。你可能也想要閱讀這篇文章 更深入了解如何使用這個 function。
// This component is loaded dynamically
const SomeComponent = React.lazy(() => import('./SomeComponent'));
請注意當你使用 lazy
component 的時候,你的 render tree 上層中必須包含一個 <React.Suspense>
來指定 loading indicator。
備註
當你同時使用
React.lazy
以及動態 import 的時候,你的 JS 環境必須支援 Promise。IE11 以下的瀏覽器將需要 polyfill。
React.Suspense
React.Suspense
讓你指定當底下的 component 還沒準備好 render 的時候所用的 loading indicator。目前 <React.Suspense>
只支援 動態載入的 component。
// This component is loaded dynamically
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
// Displays <Spinner> until OtherComponent loads
<React.Suspense fallback={<Spinner />}>
<div>
<OtherComponent />
</div>
</React.Suspense>
);
}
在我們的 code splitting 文件 有更多資訊。請注意 lazy
component 可以在 Suspense
tree 中底下很多層 ── 你不需要把每一個 lazy
元素包起來。最好的方法是將 <Suspense>
放在你想看到 loading indicator 的地方,而在所有你想進行 code splitting 的地方使用 lazy()
。
雖然目前還不支援其他情境,我們在未來會讓 Suspense
處理更多像是抓取資料的情境。你可以在我們的未來計畫中讀到更多資訊。
備註
ReactDOMServer
還沒支援React.lazy()
與<React.Suspense>
。這是一個目前已知的限制,並會在未來解決。