无法捕获错误的情况:
class Test extends React.Component {
render() {
return (
<div>{ data.title }</div>
)
}
}
class Sub extends React.Component {
constructor(props) {
super(props);
setTimeout(() => {
throw new Error('This is a setTimeout error')
}, 1000);
}
handleClick() {
// 这种错误,建议用 try-catch 解决捕获
throw new Error('This is a btn click error');
}
render() {
return (
<p onClick={ this.handleClick.bind(this) }>This is a content.</p>
)
}
}
class App extends React.Component {
render() {
return (
<div>
{/* 无法捕获到 Sub 中的捕获不到的情况的错误 */}
<ErrorBoundary>
<Sub />
</ErrorBoundary>
{/* 把可能出错的组件用错误边界组件包裹 */}
<ErrorBoundary2>
<ErrorBoundary>
<Test />
</ErrorBoundary>
</ErrorBoundary2>
</div>
)
}
}
class ErrorBoundary extends React.Component {
state = {
hasError: false
}
static getDerivedStateFromError(error) {
// console.log(1); // 1先打印 getDerivedStateFromError渲染时调用
return { hasError: true }
}
componentDidCatch(error, info) {
// console.log(2); // 2后打印 componentDidCatch抛错后调用
console.log(error, info);
}
render() {
// 如果为真,显示备用UI
if (this.state.hasError) {
return (
// <h1>This is a error UI.</h1>
// 错误边界组件内部有错误,无法捕获:
<h1>{ data.title }</h1>
)
}
// 如果没错,显示 ErrorBoundary 包裹的本来的组件
return this.props.children;
}
}
class ErrorBoundary2 extends React.Component {
constructor(props) {
super(props);
window.onerror = function(err) {
console.log(err); // 能冒泡到 window.onerror
}
}
state = {
hasError: false
}
static getDerivedStateFromError(error) {
return { hasError: true }
}
componentDidCatch(error, info) {
console.log(error, info);
}
render() {
if (this.state.hasError) {
return (
<h1>This is a error2 UI.</h1>
)
}
return this.props.children;
}
}
ReactDOM.render(<App />, document.getElementById('app'));
import Loading from './17Loading.jsx';
import ErrorBoundary from './17ErrorBoundary.jsx';
const TestComponent = React.lazy(() => import('./17Test.jsx'));
const Test2Component = React.lazy(() => import('./17index.jsx'));
class App extends React.Component {
render() {
return (
<div>
<div>123</div>
<React.Suspense fallback={ <Loading /> }>
<ErrorBoundary>
<TestComponent />
</ErrorBoundary>
<ErrorBoundary>
<Test2Component />
</ErrorBoundary>
</React.Suspense>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('app'));
class ErrorBoundary extends React.Component {
state = {
hasError: false
}
static getDerivedStateFromError(err) {
return { hasError: true }
}
componentDidCatch(err, info) {
console.log(err, info);
}
render() {
if (this.state.hasError) {
return <h1>This is a Error UI</h1>
}
return this.props.children;
}
}
export default ErrorBoundary;
class Loading extends React.Component {
render() {
return (
<div>Loading...</div>
)
}
}
export default Loading;
class Test extends React.Component {
render() {
return (
// <div>This is a Test Component.</div>
<div>{ data.title }</div>
)
}
}
export default Test;
class Test2 extends React.Component {
render() {
return (
<div>This is a Test2 Component.</div>
)
}
}
export {
Test2
}; // 不默认导出,会导致报错:Cannot convert object to primitive value
// 因为 lazy 只支持 export default 默认导出
// 如果想要命名导出,就得做中间层,见 17index.jsx
// 17index.jsx:
// export {
// Test2 as default
// } from './17Test2.jsx';