React.js 앱의 모든 오류를 try/catch 블록으로 잡을 수 있습니까?
라이브가 아닌 리액트 어플리케이션을 만들었는데, 사용하시는 분들이 가끔 이상한 오류가 발생한다는 것을 알게 되었습니다.왜 무슨 일이 일어나는지 알 수 없고, 재현도 할 수 없습니다.
서버상의 에러 로그에 에러를 송신할 수 있도록, 앱 전체 또는 그 일부를 try/catch 블록으로 포장하는 방법이 없을까요?
지금까지 읽은 것은 렌더 함수 전체를 try/catch로 래핑할 수 있다는 것뿐입니다만, 유저 인터랙션으로 인한 에러는 검출되지 않는 것입니까?
편집
다음 솔루션은 기본적으로 동기화되어 있기 때문에 렌더링 오류만 포착합니다.이것이 JS가 작동하는 방식이며, OP가 질문한 React와는 아무런 관련이 없습니다.
오리지널 투고
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 패키지 react-error-boundary로 랩하여 폴백컴포넌트와 동작을 설정할 수 있습니다.
import {ErrorBoundary} from 'react-error-boundary';
const myErrorHandler = (error: Error, componentStack: string) => {
// ...
};
<ErrorBoundary onError={myErrorHandler}>
<ComponentThatMayError />
</ErrorBoundary>
이게 결국 내가 쓰게 된 거야
편집: React 16에서 적절한 방법을 소개했습니다. @goldylucks 답변을 참조하십시오.
componentWillMount() {
this.startErrorLog();
}
startErrorLog() {
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;
};
}
하여 React의 Batching Strategy API를 수 .try/catch모든 리액트 코드에 대응합니다. 이점은 " " "에 비해 다음과 같습니다.window.onerrorMicrosoft 등의 최신 Edge에 스택트레이스를 하지 않습니다.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/
Error boundaries너무 제한적이어서 모든 오류를 잡을 수 없습니다.
React 17에서 다음과 같은 모든 오류를 탐지합니다.
- 핸들러)
on click - .
undefined exception,syslogs
2개의 글로벌핸들러가 필요해요
// TypeScript
export function registerHandlers(store: Store) {
window.addEventListener("error", (event) => {
store.dispatch<any>(setErrorAction({ message: event.message }));
});
window.addEventListener("unhandledrejection", (event: PromiseRejectionEvent) => {
store.dispatch<any>(setErrorAction({ message: event.reason.message }));
});
}
Redux 에 합니다.Store 생성되고 는 Redx로 이동할 수 있습니다.useSelector어딘가에 표시 또는 로그(예: 저장을 위해 서버로 전송)할 수 있습니다.
, 에러, HTTP 에러로 할 수 .Axios Response Interceptor를 눌러 저장하십시오(오류에 대한 자세한 정보가 표시됩니다).그냥 좀 더 자세히 말해 봐unhandledrejection(처리되지 않은 약속 예외) 또는 가로채기에 삼켜서 두 배가 되지 않도록 합니다.
저도 같은 문제가 있었어요.디버깅 콘솔도 개발자 도구도 없는 Office 앱을 만들었기 때문에 어디서 오류가 발생했는지 알 수 없었습니다.
1개의 컴포넌트(es6 클래스)를 생성하여 모든 컴포넌트를 캐치했습니다.console메시지를 다른 배열에 저장하고 "진짜"라고 부릅니다.console기능.
log(message) {
const msg = new Log(message);
this.pushMessage(msg);
this._target.log(message);
}
어디에Log단순한 랩퍼입니다.message및 atype그리고.this._target에 대한 참고 자료입니다.window.console그래서 저도 똑같이 했어요.info,warn그리고.error.
추가로, 나는 method를 만들었다.handleThrownErrors(message, url, lineNumber)예외를 포착하기 위해
window.onerror = this.handleThrownErrors.bind(this);
적어도 클래스의 인스턴스를 만들었습니다(나는 그것을 불렀습니다).LogCollector)와 함께 창에 첨부합니다.
window.logCollector = new LogCollector();
이제 logCollector 인스턴스를 가져오는 리액트컴포넌트를 만들었습니다(window.logCollector)을 속성으로 사용합니다.반응 구성 요소는 정기적으로 수집된 메시지를 확인하고 화면에 표시합니다.
componentDidMount() {
this.setInterval(this._forceUpdate, 500);
},
_forceUpdate() {
this.setState({update: !this.state.update});
}
this.setInterval()단순히 호출하는 자체 함수입니다.window.setInterval().
그리고...render()방법:
return (
<div class="console">
{this.props.logCollector.getMessages().map(this.createConsoleMessage)}
</div>
);
주의: 다음 항목을 포함하는 것이 중요합니다.
LogCollector다른 모든 파일보다 우선합니다.메모: 위의 솔루션은 매우 심플한 버전입니다.예를 들어 다음과 같습니다.커스텀(메시지) 청취자를 추가하거나 다음 메시지를 수신할 수 있습니다.
404 Not found에러(js-files 및 css-files의 경우).
언급URL : https://stackoverflow.com/questions/31111771/can-you-catch-all-errors-of-a-react-js-app-with-a-try-catch-block
'programing' 카테고리의 다른 글
| React 및 typescript의 스타일 속성에 css 변수를 정의하는 방법 (0) | 2023.04.04 |
|---|---|
| NSJON Serialization을 통해 JSON에 null 값을 포함하려면 어떻게 해야 합니까? (0) | 2023.04.04 |
| 인터페이스를 사용하여 클래스를 시리얼화하려면 어떻게 해야 합니까? (0) | 2023.04.04 |
| Angular JS 및 웹 워커 (0) | 2023.04.04 |
| WordPress를 사용하여 제거할 때 테이블을 드롭하는 방법 (0) | 2023.04.04 |