我将axios用于Web请求,并为其创建了一个拦截器,以显示所有错误消息的烤面包机。
我正在使用react-intl进行翻译,并且拦截器中存在的一般错误消息也已翻译,因此我将拦截器与应用程序的生命周期联系在一起:
class Main extends React.Component {
componentDidMount () {
// addToastInterceptor calls back for a message that can be evaluated dynamically
// otherwise it uses axios.interceptors.response.use(...)
this.interceptor = addToastInterceptor((e) =>
this.props.intl.formatMessage({
id: 'applicationForm.basic.errorMessage'
}, {
technicalMessage: e.message
}));
}
componentWillUnmount () {
// the interceptor handle is removed when the component unmounts
removeToastInterceptor(this.interceptor);
}
render() {
// any number of child component in any depth
}
}
// The intl provider must exist in a wrapper component
export default injectIntl(Main);
这样,在安装Main
组件时,任何收到错误响应的axios调用都会触发一条敬酒消息。
我的问题如下。如果我在致电Main.componentDidMount
之前尝试通过axios进行呼叫,则该消息将不会显示。
如果我在后代组件的componentDidMount
中进行呼叫,它将不会显示以下消息:
// This component dispatches a redux call that uses axios.get internally
class SomeChild extends React.Component {
componentDidMount () {
// this is
this.props.getCountriesAction();
}
}
const mapStateToProps = state => ({
countries: state.boarding.countries,
});
const mapDispatchToProps = dispatch => bindActionCreators({
getCountriesAction: getCountries,
}, dispatch);
export default connect(
mapStateToProps,
mapDispatchToProps,
)(SomeChild);
一种解决方法是使用Main的构造函数(或componentWillMoount)注册拦截器,但这不会阻止异步渲染,因为不能保证这些方法只能运行一次。
我可以以某种方式更改两个componentDidMount
调用的顺序或为此使用其他任何生命周期方法吗?
答案 0 :(得分:0)
我不确定addToastInterceptor
会做什么。我认为可以在constructor
中调用它。
如果在儿童的生命周期方法之前确实需要在componentDidMount
内部完成某些工作,则可以使用标志来延迟儿童渲染,直到一切准备就绪:
class Main extends React.Component {
state = {isReady: false}
componentDidMount () {
// addToastInterceptor calls back for a message that can be evaluated dynamically
// otherwise it uses axios.interceptors.response.use(...)
this.interceptor = addToastInterceptor((e) =>
this.props.intl.formatMessage({
id: 'applicationForm.basic.errorMessage'
}, {
technicalMessage: e.message
}));
this.setState({isReady: true});
}
render {
if (!this.state.isReady) return null;
...
}
}
如果componentDidMount
内部的工作需要很长时间,并且您想要渲染某些东西,则可以将isReady
标志传递给子级,并将其逻辑从componentDidMount
移到componentDidUpdate
:
componentDidUpdate(prevProps) {
if (this.props.isReady && this.props.isReady !== prevProps.isReady) {
/* child's logic from componentDidMount */
}
}