代码之家  ›  专栏  ›  技术社区  ›  SamVK

如何避免componentDidCatch()多次触发某些内容?

  •  0
  • SamVK  · 技术社区  · 6 年前

    componentDidCatch() 会因为同样的错误发射10次。目前,我在catch上发出一个API请求来记录错误,但我只希望记录该错误 一旦 .

    我的第一个想法是拯救我自己 prevError error 传递给 组件didcatch() 是一样的。但那不起作用 setState setState() 接受具有最新状态的回调,但到那时错误将 总是 等于 上一个错误 . 我的意思是:

    componentDidCatch(error, info) {
        this.setState({ error: true });
    
        const isNewError = (error.toString() !== this.state.prevError.toString());
        // always true since setState is async
        if (isNewError) {
           logErrorToMyService(error, info); // should only run once
           this.setState({ prevError: error });
        }
    }
    

    我也不认为我能用 componentDidUpdate() 不知为什么,因为那不知道我的错误。

    我遗漏了什么吗?我只是处理这个问题错了,需要重新处理吗(也许把支票转到 logErrorToMyService 相反呢?


    const logErrorToMyService = () => console.warn('I should only be run once');
    
    class ErrorBoundary extends React.Component {
      state = {
        error: false,
        prevError: new Error(), 
      }
      
      componentDidCatch(error, info) {
        this.setState({ error: true });
        
        // none of the below code will work correctly
        const isNewError = (error.toString() !== this.state.prevError.toString());
        // always true since setState is async
        if (isNewError) {
           logErrorToMyService(error, info); // should only run once
           this.setState({ prevError: error });
        }
      }
      
      render() {
        if (this.state.error) {
          return <div>Something went (purposefully) wrong.</div>;
        }
        return this.props.children;
      }  
    }
    
    // below is 10 purposefully buggy component instances
    const BuggyComponent = () => (
        <div>{purposefully.throwing.error}</div>
    )
    
    const App = () => (
      <ErrorBoundary>
        {[...Array(10)].map((_, i) => <BuggyComponent key={i} />)}
      </ErrorBoundary>
    )
    
    ReactDOM.render(
      <App />,
      document.getElementById('root')
    );
    <div id='root'></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.3.1/umd/react.development.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.3.1/umd/react-dom.development.js"></script>

    更新 上一个错误 不同的 之间的错误-也被跳过。

    1 回复  |  直到 6 年前
        1
  •  1
  •   ChrisG    6 年前

    在你发布的代码中, componentDidCatch() setstate 回调首次运行。然而 prevError state ,因为这与组件的外观无关。

    只需将其作为类变量来实现,这样就可以同步设置它。