React 16
MIT License
採用新核心 Fiber
- 提升渲染效率: Split rendering work into chunks and spread it out over multiple frames.
- 支援新的
render()return type - 支援新的 portal 渲染方式
React.Component 新特徵
Portal
- FEATURE:
- 在元件中, 可以指定渲染 child 在元件外的 DOM 上
- 雖然實際的 DOM Tree 上, Portal 存在於元件外, 但在 React DOM Tree 上, 仍視為存在於元件內, 因此仍會觸發 Event Bubbling.
- USAGE: 呼叫
React.createPortal(child, container) - DEMO:
class Message extends React.Component {
/**
* @param {{message:string, modalMessage:string}} props
*/
constructor(props) {
super(props);
this.state = {showModal: false};
}
render() {
let modal = null;
if (this.state.showModal) {
let body = document.body;
modal = React.createPortal(
<div className="modal">
{this.props.modalMessage}
</div>,
body
)
}
return (
<div>
<span>this.props.message</span>
<button
onClick={() => this.setState({showModal: true})}
>
show modal
</button>
{modal}
</div>
);
}
}
render()
- FEATURE:
- 能夠接受 Array Type 作為 return
- 能夠接受 Portal 作為 return
- 能夠接受 string 及 number 作為 return
- 能夠接受 boolean 及 null 作為 return
- 若 return false 或 null,
ReactDOM.findDOMNode(this)return null
- 若 return false 或 null,
Props and DOM Attributes in JSX.
- FEATURE:
- 自定義 DOM Attribute 名稱不再局限於 data- 或 aria-, 所有未被辨識為 元件 props 的屬性, 都將被視為 DOM Attributes,但仍建議以 aria- 為關鍵字
- 如賦予的值不符合 DOM Attributes 的需求, 將被轉型為字串, 且於 console 提示錯誤:
//Before
<div customattribute={new Object()} ></div>
<div customattribute={42}></div>
//After
<div customattribute="[Object object]">
<div customattribute="42"></div>
- DEMO:
class Button extends React.Component {
/**
* @param {{label:string, onClick:Function}} props
*/
constructor(props) {
super(props);
this.onClick = this.props.onClick.bind(this);
}
render() {
return (
<button onClick={this.onClick}>
{this.props.label}
</button>
);
}
}
class Container extends React.Component {
constructor(props) {
super(props);
}
render() {
let click = () => alert("Clicked");
return(
<div>
<Button label="MyButton" click={click}/>
</div>
);
}
}
//實際渲染出來的 DOM
/*
<div>
<button click="[Function click]">
MyButton
</button>
</div>
*/
元件 Update 規則調整
setState()
- FEATURE:
setState(null)將不再觸發 update- 在
render()中呼叫setUpdate, 必定觸發 update setState的 callback function 將在componentDidMount()及componentDidUpdate()後馬上觸發
componentWillMount() 及 componentWillUnmount()
- FEATURE: 若同一元件內的子元件替換, 子元件的
componentWillMount()必定先於componentWillUnmount()執行 - DEMO:
class ChildA extends React.Component {
constructor(props) {super(props);}
componentWillMount() {console.log("Child A will be mounted")}
componentWillUnmount() {console.log("Child A will be unmounted")}
render() {return <div>Child A</div>}
}
class ChildB extends React.Component {
constructor(props) {super(props);}
componentWillMount() {console.log("Child B will be mounted")}
componentWillUnmount() {console.log("Child B will be unmounted")}
render() {return <div>Child B</div>}
}
class Container extends React.Component {
constructor(props) {
super(props);
this.state = {childType: false}
}
changeChild() {
this.setState((prevState) => {
return {childType: !prevState.childType}
})
}
render() {
let child = this.state.childType ? <ChildA/> : <ChildB/>
return (<div>{child}</div>);
}
}
ReactDOM.render()
- FEATURE: 如果在元件內的生命週期函數呼叫
ReactDOM.render(), 則ReactDOM.render()return null
Error Handling
如果在元件生命週期中發生錯誤, 整個元件將不被 render, 以避免呈現有問題的資訊給使用者; 或是使用 Error Boundary 處理錯誤, 提供 error 相應的 UI.
Error Boundary
- FEATURE:
- 使用 React.Component 提供的 API, 處理 error; 並提供開發者因應 error 提供不同 UI 的時機.
- USAGE:
- 於元件中 override
componentDidCatch(error, info)API - 僅能處理元件中子元件發生的 error
- 於元件中 override
- DEMO:
class Child extends React.Component {
constructor(props) {
super(props);
}
render() {
return(<button onClick={this.props.action}>Button</button>)
}
}
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
}
componentDidCatch(error, info) {
console.log(error);
}
render() {
return (
<div>
//此處的 this.props.action 若沒定義, 若點擊, 不會觸發 componentDidCatch
<button onClick={this.props.action}>Error Button</button>
//此處因沒賦予 action 參數, 若點擊, 會觸發componentDidCatch
<Child/>
</div>
);
}
}
應用於項目中
SPEC
- 由於 React 16 使用了 ES6 的 Map 及 Set Type, 因此需要以 JavaScript Library 補齊此 Type. 官方文檔建議使用以下兩種解決方案:
- 仰賴
requestAnimationFrame
棄用 react-addons
- 個別 Addon 需要個別引用 Library
- 目前項目受影響的部分為 CSSTransitionGroup
Library 修改
| Before | After |
|---|---|
| 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 |