Fli*_*ion 33 try-catch reactjs
我做了一个没有正常运行的反应应用程序,并且使用它的人注意到偶尔会发生一些奇怪的错误.我不知道为什么或发生了什么,也无法重现它.
所以我想知道是否有办法将整个应用程序或部分应用程序包装在try/catch块中,以便我可以将错误发送到服务器上的错误日志中?
到目前为止我所读到的只是你可以将整个渲染函数包装在try/catch中,但由于用户的交互,这不能捕获任何错误吗?
Fli*_*ion 32
这就是我最终使用的东西
编辑: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;
}
}
Run Code Online (Sandbox Code Playgroud)
gol*_*cks 27
React 16引入了Error Boundaries和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;
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以将它用作常规组件:
<ErrorBoundary>
<MyWidget />
</ErrorBoundary>
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用npm包react-error-boundary包装根组件,并设置回退组件和行为.
import ErrorBoundary from 'react-error-boundary';
const myErrorHandler = (error: Error, componentStack: string) => {
// ...
};
<ErrorBoundary onError={myErrorHandler}>
<ComponentThatMayError />
</ErrorBoundary>
Run Code Online (Sandbox Code Playgroud)
Byr*_*ong 16
您可以利用React的BatchingStrategy API轻松包装try/catch所有React代码.这样做的好处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);
Run Code Online (Sandbox Code Playgroud)
完整的文章:https://engineering.classdojo.com/blog/2016/12/10/catching-react-errors/
and*_*fox 16
Error boundaries太有限并且不能捕获所有错误。
在 React 17 中,要捕获所有错误,例如:
on click),undefined exception等您需要两个全局处理程序:
// 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 }));
});
}
Run Code Online (Sandbox Code Playgroud)
Store在创建Redux 后调用此函数,所有异常都将传递给 Redux,因此您可以useSelector获取它并在某处显示或记录(例如发送到服务器进行存储)。
为了更好地覆盖 HTTP 错误,您可以捕获它们Axios Response Interceptor并从那里推送到存储(您将获得有关错误的更多信息)。只需将其安装在unhandledrejection(未处理的承诺异常)或吞入拦截器中,这样它就不会加倍。
| 归档时间: |
|
| 查看次数: |
33868 次 |
| 最近记录: |