New render return type
React16之前,組件必須return時必須被一個父元素(例如div)所包裹起來,這樣有時就會有增加冗餘的dom結構(有講究的前端怎麼能忍)。
於是React16便提供幾種新的返回類型:
- 數組或Fragment:可以返回多個元素
const arrayType = () => (
[
<li key="A">1</li>,
<li key="B">2</li>,
<li key="C">3</li>,
'tips:need key and commas, string must be wrapped in quotes',
]
);
或
const arrayType = () => (
// Key is the only attribute that can be passed to Fragment
<Fragment key="keys">
<li key="A">1</li>
<li key="B">2</li>
<li key="C">3</li>
tips:
no need key and commas, string no need be wrapped in quotes
</Fragment>
);
- 字符串或數值:將返回文本節點
const stringType = () => 'hello world!';
Error Boundaries
在React之前的版本,組件內部中的js錯會導致React渲染失敗。例如:後端返回一個List<Object>,假設Object有個name屬性,然後使用了toLowerCase()方法。但是當name的值爲null時,這將導致React渲染失敗報錯。React16.0引入“Error Boundary”來解決這類問題。
Error boundaries是一個類組建,並且定義了componentDidCatch(error, info)這個新的生命週期函數,componentDidCatch可以捕獲的到子組件內render和其他生命週期函數內的錯誤,並展示出來。
1.創建一個ErrorBoundary組件
// ErrorBoundary
export default class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = {
hasError: false,
errInfo: '',
};
}
componentDidCatch(error, info) {
console.log(error, info);
this.setState({
hasError: true,
errInfo: info,
});
}
render() {
const { hasError, errInfo } = this.state;
if (hasError) {
return (<h4>{errInfo.componentStack}</h4>);
}
return (
<Fragment>
<h4>noError!</h4>
<div>
{this.props.children}
</div>
</Fragment>
);
}
2.ErrorBoundary捕獲子組件render內的錯誤
const errorList = (props) => {
const { list } = props;
return (
list.map((item, index) => (
<ul key={index}>
{/* error */}
<li>{item.toLowerCase()}</li>
</ul>
))
);
};
export default class App extends React.PureComponent {
constructor() {
super();
this.dataList = [
'First item',
'Second item',
'Third item',
null,
];
}
render() {
return (
<Fragment>
<ErrorBoundary>
<ErrorList
list={this.dataList}
/>
</ErrorBoundary>
</Fragment>
);
}
}
注意:ErrorBoundary只能捕獲其子組件中的錯誤,而不能捕獲其組件本身的錯誤和非子組件中的錯誤。例如:
<ErrorBoundary>
{null.toLowerCase()}
</ErrorBoundary>
3.ErrorBoundary捕獲子組件生命週期內的錯誤
export default class errorLifecycle extends React.PureComponent {
constructor() {
super();
}
componentDidMount() {
throw new Error('error in componentDidMount');
}
render() {
return (
<Fragment>
hello world!
</Fragment>
);
}
}
export default class App extends React.PureComponent {
constructor() {
super();
}
render() {
return (
<Fragment>
<ErrorBoundary>
<ErrorLifeCycle />
</ErrorBoundary>
</Fragment>
);
}
}
注意:ErrorBoundary不能捕獲事件處理函數中的異常。例如:
handleClick(e) {
try {
...
} catch(err) {
...
}
}
4.當ErrorBoundary包含多個子組件時,其中任何一個子組件內部發生錯誤時就會被componentDidMount捕獲到
5.ErrorBoundary不支持SSR
代碼示例:https://github.com/MirrorHuang/react16-demo