删除文章

确定要删除这篇文章吗?

取消
确定

Can only update a mounted or mounting component.

     阅读(826)  2017-02-22 22:11:05

react native Warning: setState(...): Can only update a mounted or mounting component.

碰到这个问题根据给的提示大概意思是:setState方法仅适用于一个安装好的或者正在安装的组件,出现这个提示通常意味着你在组件卸载之后调用了这个方法。
代码如下,这是一个倒计时组件:

/**
 * Created by tujiaw on 2017/2/19.
 */

import React, { Component } from 'react';
import {
  Text,
  View,
  StyleSheet,
  TouchableHighlight,
} from 'react-native';

export default class CountDown extends Component {
  constructor(props) {
    super(props)
    this.state = {
      time: this.props.time ? this.props.time : 60,
      disabled: true
    }
    this._countdown = this._countdown.bind(this)
    this._onPress = this._onPress.bind(this)
  }

  componentDidMount() {
    this._countdown();
  }

  _onPress(){
    if (this.state.disabled) {
      //nothing
    } else {
      this.setState({disabled: true});
      this._countdown();
      if(this.props.onPress){
        this.props.onPress();
      }
    }
  }

  _countdown(){
    var that = this
    var timer = function () {
      var time = that.state.time - 1;
      that.setState({time: time});
      if (time > 0) {
        setTimeout(timer, 1000)
      } else {
        that.setState({disabled: false});
        that.setState({time: that.props.time ? that.props.time : 60});
      }
    };

    setTimeout(timer, 1000)
  }

  render() {
    var style = [styles.text];
    var component;
    if (this.state.disabled) {
      component =
        <View style={styles.container}>
          <TouchableHighlight>
            <Text style={styles.disabledText}>{this.props.text}({this.state.time})</Text>
          </TouchableHighlight>
        </View>
    } else {
      component =
        <View>
          <TouchableHighlight
            style={styles.container}
            onPress={this._onPress.bind(this)}>
            <Text style={styles.enableText}>{this.props.endText || '重新获取'}</Text>
          </TouchableHighlight>
        </View>
    }
    return (
      component
    )
  }
}

var styles = StyleSheet.create({
  container: {
    flexDirection: 'row',
    width: 100,
    height: 40,
    backgroundColor: '#ed7b66',
    margin: 10,
    justifyContent: 'center',
    alignItems: 'center',
    borderRadius: 4,
  },
  disabledText: {
    color: '#fff',
  },
  enableText: {
    color: '#fff',
  }
});

可以看到在 _countdown方法中每秒中调用一次timer方法去递减秒数,当组件unmounted之后这个timer并没有停止,所以出现了上面的问题。

解决办法:

将每次setTimeout返回的ID保存起来,在componentWillUnmount方法中clearTimeout

修改后的代码片段如下:

  componentWillUnmount() {
    clearTimeout(this.state.timeid)
  }

  _countdown(){
    var that = this
    var timer = function () {
      var time = that.state.time - 1;
      that.setState({time: time});
      if (time > 0) {
        that.setState({ timeid: setTimeout(timer, 1000) })
      } else {
        that.setState({disabled: false});
        that.setState({time: that.props.time ? that.props.time : 60});
      }
    };

    this.setState({ timeid: setTimeout(timer, 1000) })
  }

文章评论

Keep it simple,stupid
文章数
292
总访问量
350268
今日访问
282
最近评论

xuehaoyun : 很不错,来围观一下
tujiaw : 抱歉csdn code服务关闭了,这个代码我也找不到了
于淞 : 你好,这个文章的源码能分享一下吗,songsong9181@163.com,谢谢了 上面的写错了
于淞 : 你好,这个文章的源码能分享一下吗,838106303@163.com,谢谢了 上面的链接不能用了
tujiaw : 多谢多谢
essaypinglun college-paper.org : 很好的博客,赞赞
Folly : 这个实现有点奇怪,Qt为什么没有统一的比对方法。
过多s : alert("hello, world!")
tujiaw : 还不错哦
回到顶部