在前端开发中,判断边界条件和重要,通常我们要花费开发中的很大一部分时间做边界条件处理。发送ajax请求时,假设有这样一个需求: 每个页面发送ajax请求,如果请求失败,在页面上统一弹出样式一样的错误提示。这该怎么做呢?
每个页面都去引用一个错误提示组件,然后在业务逻辑中去一遍遍写错误处理的代码吗?显然有点low,这个时候,可以用React中的高阶组件,配合axios的拦截器,解决这个问题。
第一步,我们写出项目中的根组件:
class App extends Component {
render() {
return (
home
)
}
componentDidMount() {
axios.get('/index.json')
.then(()=>{})
.catch(()=>{})
}
}
这个组件中,我们只是做了ajax请求,失败的时候并没有做任何处理。
第二步,我们来写一个高阶组件
export default (WrappedComponent) => {
return class extends Component {
constructor(props) {
super(props)
this.state = {
error: false
}
}
componentWillMount() {
axios.interceptors.response.use((response) => {
return response;
}, (error) => {
this.setState({
error: true
})
return Promise.reject(error);
});
}
render() {
const errorElem = this.state.error ?
请求出错了 : null
return (
{ errorElem }
)
}
}
}
在高阶组件中,我们对原始组件做了一个封装,在组件外部增加了一个请求出错提示的div,然后通过高阶组件的state数据控制div的隐藏和显示,而何时隐藏和显示,要看axios注入器的处理情况,如果请求正常发送,div不会显示,如果请求异常,高阶组件会把div显示出来。
另外我们把拦截器定义在componentWillMount中,是为了在页面执行ajax请求发送之前,就把拦截器准备好。如果放在componentDidMount中,会导致拦截器拦截不到子组件的请求异常,因为父组件要等所有子组件的componentDidMount都执行完毕,才会执行自己的componentDidMount,这个时候增加拦截器,已经无法对子组件发出的请求做拦截了。
最后一步,我们要对整个应用的最外层应用一下高阶组件,记得,一定要把高阶组件用在最外层组件上,不然有可能会导致axios拦截器多次被定义,产生代码bug。
const HocApp = hoc(App)
ReactDOM.render(, document.getElementById('root'));
通过上面几步代码,我们就实现了想要的功能,无论你在App下增加多少层子组件,只要组件中ajax发生错误,就会在页面上显示出来
请求出错了这段内容。
这个实现是目前想到的一个实现方式,大家如果有其他方式,欢迎留言探讨!