温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

React16中异常处理的示例分析

发布时间:2021-08-19 14:22:20 来源:亿速云 阅读:155 作者:小新 栏目:web开发

这篇文章主要介绍React16中异常处理的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

异常处理

在 React 15.x 及之前的版本中,组件内的异常有可能会影响到 React 的内部状态,进而导致下一轮渲染时出现未知错误。这些组件内的异常往往也是由应用代码本身抛出,在之前版本的 React 更多的是交托给了开发者处理,而没有提供较好地组件内优雅处理这些异常的方式。在 React 16.x 版本中,引入了所谓 Error Boundary 的概念,从而保证了发生在 UI 层的错误不会连锁导致整个应用程序崩溃;未被任何异常边界捕获的异常可能会导致整个 React 组件树被卸载。所谓的异常边界即指某个能够捕获它的子元素(包括嵌套子元素等)抛出的异常,并且根据用户配置进行优雅降级地显示而不是导致整个组件树崩溃。异常边界能够捕获渲染函数、生命周期回调以及整个组件树的构造函数中抛出的异常。

我们可以通过为某个组件添加新的 componentDidCatch(error, info) 生命周期回调来使其变为异常边界:

class ErrorBoundary extends React.Component {
 constructor(props) {
super(props);
this.state = { hasError: false };
 }

 componentDidCatch(error, info) {
  // Display fallback UI
this.setState({ hasError: true });
  // 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 <h2>Something went wrong.</h2>;
  }
return this.props.children;
 }
}

然后我们就可以如常使用该组件:

<ErrorBoundary>
<MyWidget />
</ErrorBoundary>

componentDidCatch() 方法就好像针对组件的 catch {} 代码块;不过 JavaScript 中的 try/catch 模式更多的是面向命令式代码,而 React 组件本身是声明式模式,因此更适合采用指定渲染对象的模式。需要注意的是仅有类组件可以成为异常边界,在真实的应与开发中我们往往会声明单个异常边界然后在所有可能抛出异常的组件中使用它。另外值得一提的是异常边界并不能捕获其本身的异常,如果异常边界组件本身抛出了异常,那么会冒泡传递到上一层最近的异常边界中。

在真实地应用开发中有的开发者也会将崩坏的界面直接展示给开发者,不过譬如在某个聊天界面中,如果在出现异常的情况下仍然直接将界面展示给用户,就有可能导致用户将信息发送给错误的接受者;或者在某些支付应用中导致用户金额显示错误。因此如果我们将应用升级到 React 16.x,我们需要将原本应用中没有被处理地异常统一包裹进异常边界中。譬如某个应用中可能会分为侧边栏、信息面板、会话界面、信息输入等几个不同的模块,我们可以将这些模块包裹进不同的错误边界中;这样如果某个组件发生崩溃,会被其直属的异常边界捕获,从而保证剩余的部分依然处于可用状态。同样的我们也可以在异常边界中添加错误反馈等服务接口以及时反馈生产环境下的异常并且修复他们。完整的应用代码如下所示:

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>
     <h3>Something went wrong.</h3>
     <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;
 } 
}

class BuggyCounter extends React.Component {
constructor(props) {
super(props);
this.state = { counter: 0 };
this.handleClick = this.handleClick.bind(this);
 }

 handleClick() {
this.setState(({counter}) => ({
   counter: counter + 1
  }));
 }

 render() {
if (this.state.counter === 5) {
   // Simulate a JS error
throw new Error('I crashed!');
  }
return <h2 onClick={this.handleClick}>{this.state.counter}</h2>;
 }
}

function App() {
return (
  <div>
   <p>
    <b>
     This is an example of error boundaries in React 16.
     <br /><br />
     Click on the numbers to increase the counters.
     <br />
     The counter is programmed to throw when it reaches 5. This simulates a JavaScript error in a component.
    </b>
   </p>
   <hr />
   <ErrorBoundary>
    <p>These two counters are inside the same error boundary. If one crashes, the error boundary will replace both of them.</p>
    <BuggyCounter />
    <BuggyCounter />
   </ErrorBoundary>
   <hr />
   <p>These two counters are each inside of their own error boundary. So if one crashes, the other is not affected.</p>
   <ErrorBoundary><BuggyCounter /></ErrorBoundary>
   <ErrorBoundary><BuggyCounter /></ErrorBoundary>
  </div>
 );
}



ReactDOM.render(
 <App />,
 document.getElementById('root')
);

以上是“React16中异常处理的示例分析”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI