можете ли вы поймать все ошибки React.приложение js с блоком try/catch?

Я сделал приложение react, которое не работает в прямом эфире, и люди, которые его используют, отмечают, что очень иногда возникает какая-то странная ошибка. Я не знаю, почему и что происходит, и не могу воспроизвести его.

поэтому мне интересно, есть ли способ обернуть все приложение или его части в блок try/catch, чтобы я мог отправить ошибки в журнал ошибок на сервере?

все, что я прочитал до сих пор, это то, что вы можете обернуть всю функцию рендеринга в try/catch, но это не поймает ли каких-либо ошибок из-за взаимодействия с пользователем?

4 ответов


React 16 введен Границы Ошибки и метод жизненного цикла componentDidCatch:

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 <h1>Something went wrong.</h1>;
    }
    return this.props.children;
  }
}

затем вы можете использовать его как обычный компонент:

<ErrorBoundary>
  <MyWidget />
</ErrorBoundary>

или вы можете обернуть свой корневой компонент пакетом npm реагировать-ошибка-граница, и установите резервный компонент и поведение.

import ErrorBoundary from 'react-error-boundary';

const myErrorHandler = (error: Error, componentStack: string) => {
  // ...
};

<ErrorBoundary onError={myErrorHandler}>
  <ComponentThatMayError />
</ErrorBoundary>

вот что я в конечном итоге с помощью

EDIT: React 16 представил правильные способы сделать это, см. ответ @goldylucks.

componentWillMount: function ()
{
    this.startErrorLog();
}
startErrorLog:function()
{
    window.onerror = (message,file,line,column,errorObject) =>
    {
        column = column || (window.event && window.event.errorCharacter);
        var stack = errorObject ? errorObject.stack : null;

        //trying to get stack from IE
        if(!stack)
        {
            var stack = [];
            var f = arguments.callee.caller;
            while (f)
            {
                stack.push(f.name);
                f = f.caller;
            }
            errorObject['stack'] = stack;
        }

        var data = {
            message:message,
            file:file,
            line:line,
            column:column,
            errorStack:stack,
        };

        //here I make a call to the server to log the error

        //the error can still be triggered as usual, we just wanted to know what's happening on the client side
        return false;
    }
}

вы можете использовать API BatchingStrategy React, чтобы легко обернуть try/catch вокруг всего вашего кода реакции. Благо это window.onerror это то, что вы получаете хорошую трассировку стека во всех браузерах. Даже современные браузеры, такие как Microsoft Edge и Safari, не предоставляют трассировки стека в window.onerror.

вот как это выглядит с 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 {
        // dispatch redux action notifying the app that an error occurred.
        // replace this with whatever error handling logic you like.
        store.dispatch(appTriggeredError(e));
      } finally {
        isHandlingError = false;
      }
    }
  },
};

ReactUpdates.injection.injectBatchingStrategy(ReactTryCatchBatchingStrategy);

полная запись здесь:https://engineering.classdojo.com/blog/2016/12/10/catching-react-errors/


у меня была та же проблема. Я создал приложение Office, где у меня не было ни консоли отладки, ни инструментов разработчика, поэтому я не мог узнать, где произошли ошибки.

я создал один компонент (es6-класс), который захватил все console сообщения, сохраненные сообщение в отдельный массив и называется "real"