reactjs - 在父componentDidMount之后在React子中执行代码
问题描述
我将 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 调用都会触发 toast 消息。
我的问题如下。如果我在调用之前尝试使用 axios 进行调用,Main.componentDidMount
则该消息将不会显示。
如果我在后代组件中进行调用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)来注册拦截器,但这不会支持异步渲染,因为这些方法不能保证只运行一次。
我可以以某种方式更改 2 个componentDidMount
调用的顺序或为此使用任何其他生命周期方法吗?
解决方案
我不确定是什么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 */
}
}
推荐阅读
- python - Excel with pandas - 一旦读取,pandas 不会考虑对 xlsx 文件所做的更改
- kernel - Linux 内核的 dump_stack 结果中的后缀“*.part”和“.cold”是什么意思?
- mysql - Laravel 迁移时无法创建多个主键
- python - Python中图实现中的循环检测
- laravel - 如何将电子邮件模板翻译成不同的语言?
- python - 无法对列表变量求和
- java - Thread.sleep() / robot.delay() 更准确?
- xml - xsl:相邻元素的值
- c# - 一天中班次的日期时间范围分为 10 分钟的间隔 C#
- swift - 不会发生在 for 循环 (UIKit) 中对 SwiftUI 状态变量的更改