UI的某一部分抛错不该该致使整个App都崩掉,React 16由此提出一个新概念叫“error boundary”,错误边界html
“error boundary”是什么呢,是一个React组件。error boundary能捕获子组件树中发生的任何错误,而后打日志,返回fallback UI。react
error boundary能捕获哪儿的错误:git
error boundary不能捕获哪儿的错误:github
setTimeout
or requestAnimationFrame
callbacks)若是一个组件定义了static getDerivedStateFromError()或componentDidCatch()或两个都有,那么这个组件就是一个error boundary。npm
static getDerivedStateFromError()用于抛错后返回fallback UI,componentDidCatch()用于打错误日志浏览器
下面举个例子babel
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}
componentDidCatch(error, info) {
// You can also log the error to an error reporting service
logErrorToMyService(error, info);
}
render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
复制代码
而后就能把组件在ErrorBoundary里就能够了app
<ErrorBoundary>
<MyWidget /> </ErrorBoundary>
复制代码
ErrorBoundary至关于组件的catch{}块。只要class型的组件能用ErrorBoundary,function型的不能用。异步
一般实践推荐在App里一处定义,到处使用ide
注意,ErrorBoundary只catch它子组件的错,它自个儿的错不catch。固然了,若是ErrorBoundary抛错了那它会传到它上面的ErrorBoundary去处理。
Check out this example of declaring and using an error boundary with React 16.
随便,看你怎么写。包裹整个APP也成,包裹一个小组件也成
这个变化意义重大。对于React 16来讲,未被Error Boundaries捕获的错误会 unmount 整个react组件树
为啥这么作呢?React的人认为,宁肯我给整个APP都挂掉也比返一个部分挂掉的UI强。比方说通讯类app,一个挂掉的UI可能致使信息发错人;再比方说支付类APP,显示错误的帐户余额还不如啥都不显示
多用Error Boundaries更带来更好的用户体验。Facebook Messenger 给sidebar,info panel,conversation log都各自包了一层ErrorBoundary,这样某个组件挂了不会影响其余的,并且能展现不一样的fallback UI
推荐你用一些JS错误汇报工具
Create React App默认配置的,若是没用要加 this plugin到babel。
开发环境使用,生产环境禁用!
组件堆栈跟踪的组件名是调Function.name
获得的,低版本浏览器本身polyfill
try/catch只适用于当即执行的代码
try {
showButton();
} catch (error) {
// ...
}
复制代码
可是react组件是声明式的,说明将要渲染什么,Error boundaries保留了react声明式的特色
blabalbla...
Error boundaries do not catch errors inside event handlers!
渲染的时候不会处理事件的,因此事件处理程序抛错react会知道的。
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = { error: null };
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
try {
// Do something that could throw
} catch (error) {
this.setState({ error });
}
}
render() {
if (this.state.error) {
return <h1>Caught an error.</h1>
}
return <div onClick={this.handleClick}>Click Me</div>
}
}
复制代码
unstable_handleError 改为了 componentDidCatch
这部分变化codemod能够帮你自动迁移代码