在我的许多组件中,我需要执行以下操作:
handleSubmit() {
this.setState({loading: true})
someAsyncFunc()
.then(() => {
return this.props.onSuccess()
})
.finally(() => this.setState({loading: false}))
}
函数代码
加载
应保持真实,直到问题得到解决)如果函数卸载组件,。setState({loading:false})
显然会触发一个警告无法对未安装的组件调用setState(或forceUpdate)代码>
我的两个问题:
componentDidMount
和componentWillUnmount
中设置一些\u isMounted
变量,然后在需要时在我的大多数组件中检查它,而且下次写类似这样的东西时,我可能会忘记这样做李>编辑:第二个问题对我来说比第一个问题更重要一点。如果这真的是一个问题,我只是不能在未安装的组件上调用setState
,我可能会自己找到一些解决方案。但是我很好奇我是否不能忽略它。
问题的实例:
const someAsyncFunc = () => new Promise(resolve => {
setTimeout(() => {
console.log("someAsyncFunc resolving");
resolve("done");
}, 2000);
});
class Example extends React.Component {
constructor(...args) {
super(...args);
this.state = {loading: false};
}
componentDidMount() {
setTimeout(() => this.handleSubmit(), 100);
}
handleSubmit() {
this.setState({loading: true})
someAsyncFunc()
/*
.then(() => {
return this.props.onSuccess()
})
*/
.finally(() => this.setState({loading: false}))
}
render() {
return <div>{String(this.state.loading)}</div>;
}
}
class Wrapper extends React.Component {
constructor(props, ...rest) {
super(props, ...rest);
this.state = {
children: props.children
};
}
componentDidMount() {
setTimeout(() => {
console.log("removing");
this.setState({children: []});
}, 1500)
}
render() {
return <div>{this.state.children}</div>;
}
}
ReactDOM.render(
<Wrapper>
<Example />
</Wrapper>,
document.getElementById("root")
);
.as-console-wrapper {
max-height: 100% !important;
}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>
不幸的是,你必须自己跟踪“isMounted”。为了简化控制流程,可以使用async/await
:
handleSubmit() {
this.setState({loading: true})
try {
await someAsyncFunction()
await this.props.onSuccess()
} finally {
if (this._isMounted) {
this.setState({loading: false})
}
}
}
react文档中实际提到了这一点,它指向此解决方案:https://gist.github.com/bvaughn/982ab689a41097237f6e9860db7ca8d6
如果您的某些AsyncFunction
支持取消,那么您应该像本文所鼓励的那样在组件中执行此操作。但是,然后-当然-检查返回值,最终不调用this.props.on成功
。
class myClass extends Component {
_isMounted = false;
constructor(props) {
super(props);
this.state = {
data: [],
};
}
componentDidMount() {
this._isMounted = true;
this._getData();
}
componentWillUnmount() {
this._isMounted = false;
}
_getData() {
axios.get('example.com').then(data => {
if (this._isMounted) {
this.setState({ data })
}
});
}
render() {
...
}
}
您应该能够使用这个_i安装
,检查组件是否已实际安装。
handleSubmit() {
this.setState({loading: true})
someAsyncFunc()
.then(() => {
return this.props.onSuccess()
})
.finally(() => {
if (this && this._isMounted) { // check if component is still mounted
this.setState({loading: false})
}
})
}
但是请注意,这种方法被认为是一种模式。https://reactjs.org/blog/2015/12/16/ismounted-antipattern.html