面试题答案
一键面试策略
- 显示友好提示:向用户展示一个友好的错误提示,告知他们发生了错误,但应用正在努力恢复。这样可以避免用户因为看到空白页面或异常行为而感到困惑。
- 重置组件状态:尝试重置引发错误的组件到一个已知的稳定状态。例如,如果是一个表单组件抛出错误,可以将表单重置为初始状态。
- 重试机制:对于一些可能是临时性的错误,提供重试功能。比如网络请求失败导致的错误,用户可以点击重试按钮再次尝试操作。
- 回滚操作:如果错误发生在某个操作过程中,尝试回滚该操作,以确保应用状态的一致性。
代码示例
- 显示友好提示
import React, { Component } from'react'; class ErrorBoundary extends Component { constructor(props) { super(props); this.state = { hasError: false }; } componentDidCatch(error, errorInfo) { console.log('捕获到错误:', error, errorInfo); this.setState({ hasError: true }); } render() { if (this.state.hasError) { return ( <div> <p>很抱歉,发生了一个错误。我们正在努力恢复。</p> </div> ); } return this.props.children; } } class ErrorProneComponent extends Component { render() { throw new Error('模拟错误'); return <div>这部分不会渲染</div>; } } function App() { return ( <ErrorBoundary> <ErrorProneComponent /> </ErrorBoundary> ); } export default App;
- 重置组件状态
import React, { Component } from'react'; class ErrorBoundary extends Component { constructor(props) { super(props); this.state = { hasError: false }; } componentDidCatch(error, errorInfo) { console.log('捕获到错误:', error, errorInfo); this.setState({ hasError: true }); } render() { if (this.state.hasError) { // 重置子组件状态的逻辑,这里假设子组件有reset方法 return ( <div> <p>发生错误,正在重置...</p> {React.cloneElement(this.props.children, { reset: true })} </div> ); } return this.props.children; } } class ErrorProneForm extends Component { constructor(props) { super(props); this.state = { value: '' }; } handleChange = (e) => { this.setState({ value: e.target.value }); if (this.state.value === 'error') { throw new Error('模拟表单错误'); } }; render() { if (this.props.reset) { this.setState({ value: '' }); } return ( <div> <input type="text" value={this.state.value} onChange={this.handleChange} /> </div> ); } } function App() { return ( <ErrorBoundary> <ErrorProneForm /> </ErrorBoundary> ); } export default App;
- 重试机制
import React, { Component } from'react'; 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, errorInfo }); } retry = () => { this.setState({ hasError: false, error: null, errorInfo: null }); }; render() { if (this.state.hasError) { return ( <div> <p>发生错误: {this.state.error.message}</p> <button onClick={this.retry}>重试</button> </div> ); } return this.props.children; } } class ErrorProneNetworkComponent extends Component { constructor(props) { super(props); this.state = { data: null }; this.fetchData = this.fetchData.bind(this); } componentDidMount() { this.fetchData(); } fetchData() { // 模拟网络请求失败 throw new Error('网络请求失败'); // 实际中应该使用如fetch等进行网络请求 // fetch('your - api - url') // .then(response => response.json()) // .then(data => this.setState({ data })); } render() { return ( <div> {this.state.data? ( <p>数据: {JSON.stringify(this.state.data)}</p> ) : ( <p>加载数据中...</p> )} </div> ); } } function App() { return ( <ErrorBoundary> <ErrorProneNetworkComponent /> </ErrorBoundary> ); } export default App;
- 回滚操作
import React, { Component } from'react'; class ErrorBoundary extends Component { constructor(props) { super(props); this.state = { hasError: false }; } componentDidCatch(error, errorInfo) { console.log('捕获到错误:', error, errorInfo); this.setState({ hasError: true }); // 调用父组件的回滚函数,假设父组件传递了rollback方法 if (typeof this.props.rollback === 'function') { this.props.rollback(); } } render() { if (this.state.hasError) { return ( <div> <p>发生错误,已回滚操作。</p> </div> ); } return this.props.children; } } class ErrorProneTransactionComponent extends Component { constructor(props) { super(props); this.state = { balance: 100 }; this.makeTransaction = this.makeTransaction.bind(this); } makeTransaction() { // 模拟交易操作,假设扣除50 const newBalance = this.state.balance - 50; if (newBalance < 0) { throw new Error('余额不足'); } this.setState({ balance: newBalance }); } rollback() { this.setState({ balance: 100 }); } render() { return ( <div> <p>余额: {this.state.balance}</p> <button onClick={this.makeTransaction}>进行交易</button> <ErrorBoundary rollback={() => this.rollback()}> {/* 子组件进行可能导致错误的操作 */} </ErrorBoundary> </div> ); } } function App() { return ( <ErrorProneTransactionComponent /> ); } export default App;