取消组件中的所有订阅和异步将卸载方法,如何?



由于异步方法问题,我收到错误消息。在我的终端中,我看到:

Warning: Can't call setState (or forceUpdate) on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in the componentWillUnmount method.
- node_modules/fbjs/lib/warning.js:33:20 in printWarning
- node_modules/fbjs/lib/warning.js:57:25 in warning
- node_modules/react-native/Libraries/Renderer/ReactNativeRenderer-dev.js:12196:6 in warnAboutUpdateOnUnmounted
- node_modules/react-native/Libraries/Renderer/ReactNativeRenderer-dev.js:13273:41 in scheduleWorkImpl
- node_modules/react-native/Libraries/Renderer/ReactNativeRenderer-dev.js:6224:19 in enqueueSetState
- node_modules/react/cjs/react.development.js:242:31 in setState
* router/_components/item.js:51:16 in getImage$
- node_modules/regenerator-runtime/runtime.js:62:44 in tryCatch
- node_modules/regenerator-runtime/runtime.js:296:30 in invoke
- ... 13 more stack frames from framework internals

我注意到它特别指出了getImage$

这是我在该部分使用的代码:

export default class extends Component {
constructor(props) {
super(props);
const { item } = props
const bindThese = { item }
this.boundActionCreators = bindActionCreators(bindThese)
this.state = {
image: require('../../static/logo.png'),
ready: false,
showOptions: this.props.showOptions
}
this.getImage = this.getImage.bind(this)
this.renderNotAdmin = this.renderNotAdmin.bind(this)
this.renderAdmin = this.renderAdmin.bind(this)
this.handleOutOfStock = this.handleOutOfStock.bind(this)
}
async getImage(img) {
let imgUri = await Amplify.Storage.get(img)
let uri = await CacheManager.get(imgUri).getPath()
this.setState({
image: { uri },
ready: true
})
}
componentDidMount() {
this.getImage(this.props.item.image)
}

我正在尝试弄清楚如何使用这种异步方法的componentWillUnmount。我该怎么做?

谢谢!

您可以使用 React 模式isMounted以避免此处的内存泄漏。

在构造函数中:

constructor(props) {
super(props);
this._isMounted = false;
// rest of your code
}
componentDidMount() {
this._isMounted = true;
this._isMounted && this.getImage(this.props.item.image);

}

在你的componentWillUnmount

componentWillUnmount() {
this._isMounted = false;
}

在你getImage()

async getImage(img) {
let imgUri = await Amplify.Storage.get(img)
let uri = await CacheManager.get(imgUri).getPath()
this._isMounted && this.setState({
image: { uri },
ready: true
})
}

使用基于可取消承诺模式的Axios的推荐方法。因此,您可以在卸载组件时取消任何网络调用cancelToken subscription. 这是Axios取消的资源

来自 React 博客

只需在 componentDidMount 中将 _isMounted 属性设置为 true 并设置它 在 componentWillUnmount 中为 false,并使用此变量检查您的 组件的状态。

它继续说,理想情况下,这将通过使用可取消的回调来解决,尽管第一个解决方案在这里似乎很合适。

你绝对不应该做的是使用 isMounted(( 函数,它可能已被弃用。

您需要在 componentWillUnmount(( 方法中设置 this.mount = false,在 componentDidMount(( 方法中设置 this.mount = true。

setState 更新是基于条件的需要在 componentDidMount(( 方法中声明。

componentDidMount() {
this.mounted = true;
var myVar =  setInterval(() => {
let nextPercent = this.state.percentage+10;
if (nextPercent >= 100) {
clearInterval(myVar);
}
if(this.mounted) {
this.setState({ percentage: nextPercent });
}
}, 100);
}
componentWillUnmount(){
this.mounted = false;
}

我通过覆盖setState方法解决了错误

isSubscribed = true;
componentWillUnmount() {
this.isSubscribed = false;
}
setState = (state, callback?) => {
if (this.isSubscribed) {
super.setState(state, callback);
}
}

最新更新