【问题标题】:reactjs try catch in render does not catch children errorsreactjs try catch in render 不捕获子错误
【发布时间】:2016-03-11 04:20:47
【问题描述】:

我正在尝试将错误捕获添加到组件的渲染功能中。当我在实际渲染函数中抛出错误时,这可以正常工作,但是如果组件的子组件中有错误,则 try 不会捕获错误(或者它们被子组件错误处理程序拦截,我不确定?)

有没有办法将错误强加给父级。

const SimpleComponent = React.createClass({
    render: function(){
        try{
            throw 'new error'
            return <div>{this.props.children}</div>
        }catch(e){
            console.log('error', e);        
        }
    }
})

以上工作

const SimpleComponent = React.createClass({
    render: function(){
        try{
            return <div>{this.props.children}</div>
        }catch(e){
            console.log('error', e);        
        }
    }
})

const ChildComponent = React.createClass({
    render: function(){
        throw 'child error'
    }
})

<SimpleComponent>
    <ChildComponent />
</SimpleComponent>

上面这个不明白

【问题讨论】:

  • 我不认为这就是render() 的工作原理。你真的应该避免使用任何render() 方法。任何可能抛出的工作都应该存在于其他地方。
  • 您应该使用 Prop Validation (PropTypes) 来确保组件正确呈现,您的示例不是 try catch 的正确用例 - 尝试并坚持 React 的内置实现
  • "你真的应该避免抛出任何 render()" => 可能已经有来自其他地方的组件可能会抛出
  • 你描述了我的确切问题

标签: error-handling reactjs


【解决方案1】:

使用 react 16 中的 componentDidCatch() 方法。

查看this了解更多信息

【讨论】:

    【解决方案2】:

    您可以利用 React 的 BatchingStrategy API 轻松地将 try/catch 包裹在您的所有 React 代码周围。与window.onerror 相比,这样做的好处是您可以在所有浏览器中获得很好的堆栈跟踪。即使是像 Microsoft Edge 和 Safari 这样的现代浏览器也不向 window.onerror 提供堆栈跟踪。

    请注意,此解决方案不会总是阻止 React 进入错误状态。但是,此解决方案至少允许您处理错误,例如显示错误横幅/模式,或将堆栈跟踪错误日志发送到您的服务。

    这是 React 15.4 的样子:

    import ReactUpdates from "react-dom/lib/ReactUpdates";
    import ReactDefaultBatchingStrategy from "react-dom/lib/ReactDefaultBatchingStrategy";
    
    let isHandlingError = false;
    const ReactTryCatchBatchingStrategy = {
      // this is part of the BatchingStrategy API. simply pass along
      // what the default batching strategy would do.
      get isBatchingUpdates () { return ReactDefaultBatchingStrategy.isBatchingUpdates; },
    
      batchedUpdates (...args) {
        try {
          ReactDefaultBatchingStrategy.batchedUpdates(...args);
        } catch (e) {
          if (isHandlingError) {
            // our error handling code threw an error. just throw now
            throw e;
          }
    
          isHandlingError = true;
          try {
            // replace this with whatever error handling logic you like.
            // e.g. dispatch redux action notifying the app that an error occurred:
            // `store.dispatch({type: "EXCEPTION", payload: e});`
            console.error(e);
          } finally {
            isHandlingError = false;
          }
        }
      },
    };
    
    ReactUpdates.injection.injectBatchingStrategy(ReactTryCatchBatchingStrategy);
    

    完整的文章在这里:https://engineering.classdojo.com/blog/2016/12/10/catching-react-errors/

    【讨论】:

    • 嘿拜伦。这很好 - 但你实际在哪里使用它?这在应用程序中的哪个位置?
    • @jamesemanon 您可以将此代码 sn-p 粘贴到代码库中的任何位置。 sn-p 中的关键行是 ReactUpdates.injection.injectBatchingStrategy(ReactTryCatchBatchingStrategy); 在我们的代码库中,我们将注入行放在我们的应用程序初始化文件中,就在我们调用 ReactDOM.render()
    • +1。我明白了,它对我有用,谢谢!但是这里或链接的文章中没有提到函数appTriggeredError。我认为您不妨将其取出并用例如替换它。 console.error(e) 或类似名称(但请保留您的短语“将其替换为您喜欢的任何错误处理逻辑”)。
    • @TylerCollier 好电话!是的,把它留在那里只是一个混乱的根源
    • @ByronWong 当我将它添加到我的 App.js 中时,我收到错误“ReactUpdates:必须提供批处理策略”
    【解决方案3】:

    我建议在您的组件中使用(当前)不稳定的生命周期事件unstable_handleError

    public unstable_handleError(err: any) {
    
      this.setState({
        error: err
      });
    
    }
    

    错误钩子可能会在未来的版本中成为官方 API。 详情见本期

    https://github.com/facebook/react/issues/2461

    【讨论】:

    • 您能否确认这是否会发现儿童的错误?它对我不起作用。
    • 只有在初始渲染抛出错误时才会捕获。如果更新导致渲染出现错误,它将无法正常工作
    猜你喜欢
    • 2022-12-21
    • 1970-01-01
    • 2012-11-02
    • 2016-05-21
    • 2014-03-04
    • 1970-01-01
    • 1970-01-01
    • 2015-06-21
    • 2015-03-31
    相关资源
    最近更新 更多