【问题标题】:How to check if a component is mounted in React-Native ES6如何检查组件是否安装在 React-Native ES6 中
【发布时间】:2016-05-30 09:04:21
【问题描述】:

我在我的应用程序中设置了一个监听器,并在广播时使用强制更新,但它给出了错误 forceUpdate cant be called on unmounted component。不推荐使用 isMounted() 函数后,如何检查组件是否已挂载。

'use strict';
var React = require('react-native');
import ExpAndroid from './ExpAndroid';
var {
  AppRegistry,
  Image,
  ListView,
  TouchableHighlight,
  StyleSheet,
  Text,
  View,
  Component,
  AsyncStorage,
  Navigator,
  DeviceEventEmitter
} = React;

var rowID;
var img=require('./resource/ic_pause_white.png');





class Example1 extends Component{
  constructor(props) {
    super(props);
    this.state = {

    };
  }
  componentWillMount(){

      rowID = this.props.rowIdentity;
      console.log("rowID "+rowID);

  }


componentDidMount(){
  console.log('component  mounted')
  this.start();

  DeviceEventEmitter.addListener('playMusicStatus', (data)=> {


   if(data.playMusic==true){

     img=require('./resource/ic_pause_white.png');
       rowID++;
        this.setState(this.state);
        ExpAndroid.someMethod1("someurl);


  }



});
}

componentWillUnmount(){
  console.log('componentwill  unmounted')
}

  start() {

    var  url = "some url";
    ToastAndroid.prepareToPlay(url,true);
}



render() {




     return (
      <Image source={require('./resource/album_back.png')} style={styles.background}>
      <Image
      source={{uri:this.state.trackDetails[rowID].thumnail_loc}}
      style={styles.thumbnail}
      />
      <View style={styles.flowRow}>
      <Text
      style={styles.titles}
      >text1 + {rowID}: </Text>
      <Text
      style={styles.titles}
      >{this.state.details[rowID].text1}</Text>
      </View>
      <View style={styles.flowRow}>
      <Text
      style={styles.titles}
      >text2 : </Text>
      <Text
      style={styles.titles}
      >{this.state.details[rowID].text2}</Text>
      </View>
      <View style={styles.flowRow}>
      <Text
      style={styles.titles}
      >Text3 : </Text>
      <Text
      style={styles.titles}
      >{this.state.Details[rowID].Text3}</Text>
      </View>
      <View style={styles.flowRow}>
      <Text
      style={styles.titles}
      >Text4 : </Text>
      <Text
      style={styles.titles}
      >{this.state.details[rowID].Text4}</Text>
      </View>


      </Image>
    );
  }
}
var styles = StyleSheet.create({

  container: {
    flex: 1,

  },
  background: {
    flex: 1,

    width: null,
    height: null,
  },

  flowRow : {
    flexDirection :'row',

  },
  flowRowPlay : {
    flexDirection :'row',
    alignSelf:'center',

  },
  backgroundImage: {
    flex: 1,
    resizeMode: 'cover', // or 'stretch'
  },

  thumbnail: {
    width: 100,
    height: 120,
    alignSelf:'center',
    margin :30
  },

  controls: {
    width: 30,
    height: 30,
    margin:20
  },


  titles: {
    fontSize: 15,
    margin:20,
    color: 'white',

  },
  timings: {
    fontSize: 12,
    margin:5,
    color: 'white',

  },
});

module.exports = Example1;

【问题讨论】:

    标签: react-native


    【解决方案1】:

    你可以在你的组件中自己处理这个:

    componentDidMount() { 
      this._mounted = true;
    }
    
    componentWillUnmount() {
      this._mounted = false;
    }
    

    然后你可以在你的监听器中检查this._mounted的值。

    请注意,应避免使用forceUpdate() https://facebook.github.io/react/docs/component-api.html#forceupdate

    通常你应该尽量避免使用 forceUpdate() 并且只从 render() 中的 this.props 和 this.state 中读取。这使您的组件“纯粹”并且您的应用程序更加简单和高效。

    【讨论】:

    • 在我的情况下 componentWillUnmount() 没有被调用。我已经在本机端注册了我的事件,并在 componentDidMount 中进行了响应。每当它收到该侦听器时,它都会调用 setstate 来更新视图。
    • 如果componentWillUnmount 为什么需要知道它是否已卸载?
    • 我已经更新了代码,每次收到监听器时,我都会将 rowId 更新为 1 并在其上调用 setState,但在我的情况下,它给了我错误,无法更新未挂载状态和时间行 id增加 2 或 3,然后设置状态。
    • 警告:setState(...):只能更新已安装或已安装的组件。这通常意味着您在未安装的组件上调用了 setState()。这是一个无操作。请检查未定义组件的代码。
    • 我们应该如何避免这种情况?
    【解决方案2】:

    使用ReactUpdateQueue,您可以避免管理自己的isMounted 状态。

    const ReactUpdateQueue = require('ReactUpdateQueue');
    
    // Pass the ref to your component.
    if (ReactUpdateQueue.isMounted(view)) {
      // Your component is mounted!
    }
    

    【讨论】:

    • @ThomasKekeisen 当 React 开始使用 Fiber 时,这个解决方案就坏了。
    • 是的,它现在是一种反模式 - isMounted antipattern
    【解决方案3】:

    我所做的是更改 componentWillMount 中的回调。

    let asyncCallback;
    
    componentDidMount(){
        asyncCallback = res=> this.setState({data: res});
        asyncTask(asyncCallback);
    }
    
    componentWillUnmount(){
        asyncCallback = ()=> console.log("AsyncCallback called but component has unmounted");
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-31
      • 2016-09-18
      • 1970-01-01
      • 1970-01-01
      • 2017-10-07
      • 2013-03-24
      • 1970-01-01
      相关资源
      最近更新 更多