можете ли вы поймать все ошибки 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"