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