React-Native中的组件加载、卸载与setState问题。

Warning: Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component. This is a no-op.

通常我们会在componentWillMount方法中执行异步数据请求,然后调用setState方法处理得到的数据来更新界面。有时会遇到这个警告,如下图:

警告提示我们可能在被卸载的组件上调用了setState()方法。一般情况下是在某个异步请求还未结束时组件被卸载了,但请求完毕后按照仍会按照正常流程调用setState()方法,这时就出现了上面的警告。

下面用一段代码来复现这种情况。为了方便,不使用真正的网络请求,而是使用下面的count()方法。count()方法每隔1秒调用一次setState方法将this.state.count加1,总共调用10次setState()方法。这样就有充足的时间来观察和操作。

在render()方法中,将this.state.count这个数字显示在屏幕中央。componentWillMount方法中调用count方法,组件准备加载时就开始计数,相当于进行异步的网络请求。在跳转到这个页面后,屏幕中央的数字会从0一直加到10,在加到10之前,退出这个页面,就能观察到上图所示的警告。

import React, { Component} from 'react';
import {
View,
Text,
} from 'react-native'; export default class Test extends Component {
constructor(props) {
super(props);
this.state = {
count: 0,
}
} x = 0; count = () => {
if (this.x < 10) {
this.x++;
this.setState({count: this.x});
setTimeout(this.count, 1000);
}
} componentWillMount() {
this.count();
} render() {
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text style={{fontSize: 40}}>{this.state.count}</Text>
</View>
)
}
}

实际上,这个警告能帮助我们找到程序中的bug,在一个被卸载的组件上调用setState()意味着这个组件可能没有被正确的清理掉,也就是说,程序仍然具有对这个被卸载组件的引用,这可能导致内存泄漏。

以前有一个isMounted()函数用来确定组件的状态,避免在被卸载了的组件上调用setState()方法,但是现在已经不再使用了。

要解决这个问题,可以维护一个变量_isMounted,来跟踪组件的状态。在componentDidMount()中将其设置为true,在componentWillUnmount()中将其设置为false。然后在使用setState, replaceState, or forceUpdate方法时检查组件被卸载之后是否可能被调用,如果是,则使用_isMounted变量。

修正后的代码如下。现在再重复前面的操作,在数字数到10之前退出页面,就不会出现警告了。

import React, { Component} from 'react';
import {
View,
Text,
} from 'react-native'; export default class Test extends Component {
constructor(props) {
super(props);
this.state = {
count: 0,
}
} x = 0; count = () => {
if (this.x < 10) {
this.x++;
if (this._isMounted) {
this.setState({count: this.x});
}
setTimeout(this.count, 1000);
}
} _isMounted; componentWillMount() {
this.count();
} componentWillUnmount() {
this._isMounted = false;
} componentDidMount() {
this._isMounted = true;
} render() {
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<Text style={{fontSize: 40}}>{this.state.count}</Text>
</View>
)
}
}

无isMounted:



有isMounted:

参考连接:

【React报错】isMounted is an Antipattern

isMounted is an Antipattern

[技术博客]React-Native中的组件加载、卸载与setState问题的更多相关文章

  1. [技术博客]react native事件监听、与原生通信——实现对通知消息的响应

    在react native中会涉及到很多页面之间的参数传递问题.静态的参数传递通常利用组件的Props属性,在初始化组件时即可从父组件中将参数传递到子组件中.对于非父子关系的组件来说,无法直接传递参数 ...

  2. [技术博客]React Native——HTML页面代码高亮&数学公式解析

    问题起源 原有博文显示时代码无法高亮,白底黑字的视觉效果不好. 原有博文中无法解析数学公式,导致页面会直接显示数学公式源码. 为了解决这两个问题,尝试了一些方法,最终利用开源类库实现了页面美化. (失 ...

  3. 【技术博客】Django中文件下载的实现

    开发组在开发过程中,都不可避免地遇到了一些困难或问题,但都最终想出办法克服了.我们认为这样的经验是有必要记录下来的,因此就有了[技术博客]. Django中文件下载的实现 1.背景 在VisualPy ...

  4. React Native中Touchable组件的使用

    截图如下: /** * Sample React Native App * https://github.com/facebook/react-native * @flow */ import Rea ...

  5. React Native封装Toast与加载Loading组件

    React Native开发封装Toast与加载Loading组件 在App开发中,我们避免不了使用的两个组件,一个Toast,一个网络加载Loading,在RN开发中,也是一样,React Nati ...

  6. Hexo博客部署codingNet静态资源无法加载

    用Hexo搭建的个人博客,部署到github的pages的话,好像百度搜索不到.所以在国内的codingNet的pages服务也一起部署一下,这样方便国内国外搜索引擎收录进来.具体部署教程我是参考这里 ...

  7. React Native 中吐司组件react-native-easy-toast

    https://github.com/crazycodeboy/react-native-easy-toast 用法: import Toast from 'react-native-easy-toa ...

  8. [技术博客]在团队中使用Pull Request来管理代码

    在团队中使用Pull Request来管理代码 前言 在参加多人共同开发项目,且选用Git作为代码托管工具的时候,我们不免会遇到分支冲突.覆盖.合并等问题.显然,因为同一个仓库是属于大家的,所以每个人 ...

  9. React Native中加载指示器组件ActivityIndicator使用方法

    这里讲一下React Native中的一个组件——ActivityIndicator,这是一个加载指示器,俗称菊花,很常见的,效果如下所示: 可以看到图中有两个加载指示器,一大一小,这是尺寸不是我设置 ...

随机推荐

  1. NodeJS新建服务器以及CommonJS规范

    1.什么是node.js?(1)Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效.( ...

  2. PHP获取当前脚本的绝对路径方法

    一.dirname(__FILE__) 比如:a.php所在路径为/var/www/web/a.php dirname(__FILE__)返回的则是/var/www/web/ 二.__DIR__ a. ...

  3. 一、MySQL基础知识

    一.背景介绍 我们每天都在访问各种网站.APP,如微信.QQ.抖音,今日头条等,这些东西上面都存在大量的信息,这些信息都需要有地方存储,存储在哪里呢?数据库. 所有我们需要开发一个网站.APP,数据库 ...

  4. Ubuntu 18.04 + Gtx 1660 安装Nvidia 显卡驱动

    1.UEFI禁用secure boot(我的系统是win10主系统,引导ubuntu,安装驱动前电脑存在win10 uefi引导问题) Make sure the "OS Type" ...

  5. WSGI——python web 服务器网关接口

    转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10826084.html 一:服务器.服务器软件.应用程序(后台) 我们常说“服务器”,实际上服务器是一个很宽 ...

  6. Codeforces Round #601 (Div. 2) E2. Send Boxes to Alice (Hard Version)

    Codeforces Round #601 (Div. 2) E2. Send Boxes to Alice (Hard Version) N个盒子,每个盒子有a[i]块巧克力,每次操作可以将盒子中的 ...

  7. 纯数据结构Java实现(11/11)(散列)

    欢迎访问我的自建博客: CH-YK Blog.

  8. 词向量---LSA(Latent Semantic Analysis)

    举例: 矩阵分解之后,取前两维,k=2, 单词距离:   文档距离: 通过LSA分析之后计算文档间的余弦相似度,属于同一个类型文本之间的相似度很接近:在原始文档间计算相似度,效果不如LSA 当出现新的 ...

  9. 玩转Spring--消失的事务@Transactional

    消失的事务 端午节前,组内在讨论一个问题: 一个没有加@Transactional注解的方法,去调用一个加了@Transactional的方法,会不会产生事务? 文字苍白,还是用代码说话. 先写一个@ ...

  10. server 2012/2016上,任务管理器性能页面增加磁盘监控

    1.用管理员身份启动命令行 2.命令行中输入:diskperf -y 3.关闭之前打开的任务管理,重新打开,发现可爱的磁盘监视器出现了.