在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
前言从 React 16 开始,引入了 Error Boundaries 概念,它可以捕获它的子组件中产生的错误,记录错误日志,并展示降级内容,具体 官网地址 错误边界避免一个组件错误导致整个页面白屏不能使用等情况,使用优雅降级的方式呈现备用的 UI,错误边界可以在渲染期间、生命周期和整个组件树的构造函数中捕获错误。自 React 16 起,任何未被错误边界捕获的错误将会导致整个 React 组件树被卸载 ErrorBoundary 意义
在浏览页面时,由于后端返回异常或者前端的某些错误校验,会导致用户体验很差,你想想,你带着老婆,坐着火车,吃着火锅唱着歌, 官网如何实现👉 如果一个 class 组件中定义了 static getDerivedStateFromError() 或 componentDidCatch() 这两个生命周期方法中的任意一个(或两个)时,那么它就变成一个错误边界。当抛出错误后,请使用 static getDerivedStateFromError() 渲染备用 UI ,使用 componentDidCatch() 打印错误信息 👈 class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false }; } static getDerivedStateFromError(error) { // 更新 state 使下一次渲染能够显示降级后的 UI return { hasError: true }; } componentDidCatch(error, errorInfo) { // 你同样可以将错误日志上报给服务器 logErrorToMyService(error, errorInfo); } render() { if (this.state.hasError) { // 你可以自定义降级后的 UI 并渲染 return <h1>Something went wrong.</h1>; } return this.props.children; } } 然后你可以将它作为一个常规组件去使用: <ErrorBoundary> <MyWidget /> </ErrorBoundary> 错误边界的工作方式类似于 JavaScript 的 封装一个可配置的 ErrorBoundary了解了官网实现错误边界组件的方法,我们可以封装一个 1.创造一个可配置的 ErrorBoundary 类组件相比与官网的
class ErrorBoundary extends React.Component { state = { error: false }; static getDerivedStateFromError(error) { return { error }; } componentDidCatch(error, errorInfo) { if (this.props.onError) { //上报日志通过父组件注入的函数进行执行 this.props.onError(error, errorInfo.componentStack); } } render() { const { fallback, FallbackComponent } = this.props; const { error } = this.state; if (error) { const fallbackProps = { error }; //判断是否为React Element if (React.isValidElement(fallback)) { return fallback; } //组件方式传入 if (FallbackComponent) { return <FallbackComponent {...fallbackProps} />; } throw new Error("ErrorBoundary 组件需要传入兜底UI"); } return this.props.children; } } 这样就可以对兜底 1.在 ErrorBoundary 中添加方法,检测是否有注入重置方法,如果有重置方法就执行并且重置 state 中的 error,使其错误状态为 falseresetErrorBoundary = () => { if (this.props.onReset) this.props.onReset(); this.setState({ error: false }); }; 2.在 render 中添加函数组件类型进行渲染,可以将重置的方法以及错误信息当做参数进行传递到当前组件进行处理render() { const { fallback, FallbackComponent, fallbackRender } = this.props; const { error } = this.state; if (error) { const fallbackProps = { error, resetErrorBoundary: this.resetErrorBoundary, }; ... if (typeof fallbackRender === "function")return fallbackRender(fallbackProps); ... } return this.props.children; } 2.将 ErrorBoundary 通过高阶函数进行包裹返回import React from "react"; import DefaultErrorBoundary from "./core"; const catchreacterror = (Boundary = DefaultErrorBoundary) => InnerComponent => { return props => ( <Boundary {...props}> <InnerComponent {...props} /> </Boundary> ); }; 使用&测试通过一个点击自增的 Demo,当数字到达某值,抛出异常,这里分别对 class 组件和 Function 组件作为发起异常的组件进行测试
//Function组件 const fnCount1 = ({ count }) => { if (count == 3) throw new Error("count is three"); return <span>{count}</span>; }; //Class组件 class fnCount2 extends React.Component { render() { const { count } = this.props; if (count == 2) throw new Error("count is two"); return <span>{count}</span>; } }
const errorbackfn = ({ error: { message }, resetErrorBoundary }) => ( <div> <p>出错啦</p> <pre>{message}</pre> <button onClick={resetErrorBoundary}>Try again</button> </div> );
const errorbackcom = () => <h1>出错啦,不可撤销</h1>;
//对发起异常的组件进行包裹处理,返回一个可以处理错误编辑的高阶组件 const SafeCount1 = catchreacterror()(fnCount1); const SafeCount2 = catchreacterror()(fnCount2); //测试主组件 const App = () => { const [count, setCount] = useState(0); const ListenError = (arg, info) => console.log("出错了:" + arg.message, info); //错误时进行的回调 const onReset = () => setCount(0); //点击重置时进行的回调 return ( <div className="App"> <section> <button onClick={() => setCount(count => count + 1)}>+</button> <button onClick={() => setCount(count => count - 1)}>-</button> </section> <hr /> <div> Class componnet: <SafeCount2 count={count} fallbackRender={errorbackfn} onReset={onReset} onError={ListenError} /> </div> <div> Function componnet: <SafeCount1 count={count} FallbackComponent={errorbackcom} onError={ListenError} /> </div> </div> ); }; 大功告成! 遇到的问题&总结有很多时候 react 错误边界不是万能的比如
上面 this.o 不存在,会报错,window.onerror 可以捕获,但是错误边界捕获不到。
服务端渲染 和 错误边界自己的错误 总结
至此,谢谢各位在百忙之中点开这篇文章,希望对你们能有所帮助,相信你对 react 中的错误边界有了大概的认实,也会编写一个简单的 |
请发表评论