在react尋找錯誤處理,看到一個有趣的名詞叫Error Boundaries,好像沒有中文名詞但大致的意思是錯誤的邊界。當發生錯誤時限縮錯誤範圍,不會影響到其它UI原件仍可繼續操作。而 Error Boundaries 也可定義成元件形成一個新的lifecycle,稱為 componentDidCatch(error, info) ,這比以往傳統的 try{}catch{} 方便操作。以下簡單修改官方範例,讓大家體會一下Error Boundaries與 try{}catch{} ,但在handle發生錯誤還是需要靠 try{}catch{} 才有辦法進行捕捉。
src/ErrorBoundary.js
import React, { Component } from 'react';
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { error: null, errorInfo: null };
}
componentDidCatch(error, errorInfo) {
// Catch errors in any components below and re-render with error message
this.setState({
error: error,
errorInfo: errorInfo
})
// You can also log error messages to an error reporting service here
}
render() {
if (this.state.errorInfo) {
// Error path
return (
<div>
<h2>Something went wrong.</h2>
<details style={{ whiteSpace: 'pre-wrap' }}>
{this.state.error && this.state.error.toString()}
<br />
{this.state.errorInfo.componentStack}
</details>
</div>
);
}
// Normally, just render children
return this.props.children;
}
}
export default ErrorBoundary;
src/ErrorCounter.js
import React, { Component } from 'react';
class ErrorCounter extends React.Component {
constructor(props) {
super(props);
this.state = { counter: 0, error: null };
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(({counter}) => ({
counter: counter + 1
}),
function(){
console.log(this.state.counter)
try {
if(this.props.action === "handleClick" && this.state.counter === 3) {
throw new Error('handleClick error!!');
}
} catch (error) {
this.setState({ error: error });
}
});
}
render() {
if (this.state.counter === 5) {
throw new Error('error!!');
} else if(this.state.error !== null) {
return <h1>{this.state.error}</h1>;
}
return <h1 onClick={this.handleClick}>{this.state.counter}</h1>;
}
}
export default ErrorCounter;
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import ErrorBoundary from './ErrorBoundary';
import ErrorCounter from './ErrorCounter';
import registerServiceWorker from './registerServiceWorker';
const App = () => (
<div>
<ErrorBoundary>
<ErrorCounter />
</ErrorBoundary>
<ErrorBoundary>
<ErrorCounter action={"handleClick"} />
</ErrorBoundary>
</div>
)
ReactDOM.render(
<App /> ,
document.getElementById('root'));
registerServiceWorker();
輸出畫面
此error畫面開發模式才會顯示
ErrorBoundary補捉畫面
try{}catch{}補捉畫面
參考資料:Error Boundaries
https://reactjs.org/docs/error-boundaries.html