面试题答案
一键面试1. 高阶组件封装错误边界逻辑
- 创建错误边界高阶组件
import React, { Component } from'react'; const withErrorBoundary = (WrappedComponent) => { return class ErrorBoundary extends Component { constructor(props) { super(props); this.state = { hasError: false, error: null, errorInfo: null }; } componentDidCatch(error, errorInfo) { // 记录错误,可用于日志系统 console.log('捕获到错误:', error, errorInfo); this.setState({ hasError: true, error: error, errorInfo: errorInfo }); } render() { if (this.state.hasError) { // 返回友好的错误提示界面 return ( <div> <h1>发生错误</h1> <p>{this.state.error.message}</p> <pre>{this.state.errorInfo.componentStack}</pre> </div> ); } return <WrappedComponent {...this.props} />; } }; }; export default withErrorBoundary;
- 使用高阶组件
import React from'react'; import withErrorBoundary from './withErrorBoundary'; const MyComponent = () => { // 模拟异步操作 const handleAsyncOperation = async () => { try { // 模拟异步请求 const response = await new Promise((resolve, reject) => { setTimeout(() => { reject(new Error('异步操作出错')); }, 1000); }); } catch (error) { // 这里捕获到的错误会冒泡到错误边界 throw error; } }; return ( <div> <button onClick={handleAsyncOperation}>执行异步操作</button> </div> ); }; export default withErrorBoundary(MyComponent);
2. 捕获并处理异步操作及深层嵌套组件错误
- 异步操作错误捕获
- 在异步操作内部,使用
try...catch
捕获错误。如果不捕获,错误会向上冒泡到最近的错误边界。如上述handleAsyncOperation
函数中的try...catch
块。 - 当异步操作抛出错误时,
componentDidCatch
方法会被触发,在其中可以记录错误信息,并更新状态以显示错误提示。
- 在异步操作内部,使用
- 深层嵌套组件错误捕获
- 错误边界会捕获其后代组件树中任何位置抛出的错误,无论嵌套有多深。只要是在错误边界包裹的组件树内,任何组件(包括深层嵌套组件)抛出的错误都会被捕获。
- 例如,如果有多层嵌套的组件结构:
const OuterComponent = () => { return ( <div> <MiddleComponent /> </div> ); }; const MiddleComponent = () => { return ( <div> <InnerComponent /> </div> ); }; const InnerComponent = () => { throw new Error('内层组件错误'); return <div>内容</div>; }; const WrappedOuterComponent = withErrorBoundary(OuterComponent);
- 这里
InnerComponent
抛出的错误会被withErrorBoundary
封装的错误边界捕获。
3. 保证错误处理的一致性
- 统一的错误提示界面
- 在错误边界的
render
方法中,当hasError
为true
时,返回统一的错误提示界面。这样无论哪个组件抛出错误,用户看到的都是一致的错误反馈。
- 在错误边界的
- 统一的错误记录
- 在
componentDidCatch
方法中,统一记录错误信息,无论是异步操作错误还是深层嵌套组件错误。可以将错误信息发送到日志系统,方便排查问题。
- 在
4. 性能优化
- 避免不必要的渲染
- 错误边界本身应该尽量减少不必要的渲染。在
shouldComponentUpdate
方法中,可以根据特定条件(如错误状态是否改变)来决定是否重新渲染。例如:
shouldComponentUpdate(nextProps, nextState) { return nextState.hasError!== this.state.hasError; }
- 错误边界本身应该尽量减少不必要的渲染。在
- 异步操作优化
- 对于异步操作,可以使用防抖或节流技术,减少频繁触发异步操作导致的性能问题。例如,如果是用户频繁点击按钮触发异步操作,可以使用防抖函数:
import { debounce } from 'lodash'; const MyComponent = () => { const handleAsyncOperation = async () => { try { const response = await new Promise((resolve, reject) => { setTimeout(() => { resolve('成功'); }, 1000); }); } catch (error) { throw error; } }; const debouncedHandleAsyncOperation = debounce(handleAsyncOperation, 300); return ( <div> <button onClick={debouncedHandleAsyncOperation}>执行异步操作</button> </div> ); };