React-native: Touchable Highlight in infinite loop without pressing it manually.

Created on 29 Aug 2016  路  3Comments  路  Source: facebook/react-native

--- delete everything above this line before submitting your issue ---

Issue Description

I used TouchableHighlight, I am using it for toggling Boolean value. But on render() TouchableHighlight is automatically getting pressed, and due to infinite loop my app is getting crashed. Flow of my program is as follows.
I am applying timeout in componentWillMount() and fetching Data in componentDidMount() after 3 seconds I am displaying page. I am getting data correctly and all data is showing up till I am not adding onPress property on TouchableHighlight. I am providing my complete program in code snippet section.

Steps to Reproduce / Code Snippets

          /**
           * ASAP app using react-native
           * Author:-Gaurav Bhusare
           * 
           */
          import React, {
              Component
          } from 'react';
          import {
              AppRegistry,
              StyleSheet,
              Text,
              View,
              TouchableHighlight,
              TextInput,
              Image,
              Navigator,
              AsyncStorage,
              Picker,
              Item,
              ListView,
              TabBarIOS,
              ScrollView
          } from 'react-native';
          import Tabs from 'react-native-tabs';
          //import Payments from './Payments'
          import Global from './Global';
          //import Details from './Details'

          import Dimensions from 'Dimensions';


          const width1 = Dimensions.get('window').width;
          const height1 = Dimensions.get('window').height;
          const ds = new ListView.DataSource({
              rowHasChanged: (r1, r2) =>r1 !== r2
          });

          export default class OwnerHome extends Component {
              constructor(props) {
                  super(props);
                  this.state = {

                      payments: [],
                      timePassed: false,

                      //dataSource2: ds.cloneWithRows([]),
                      unitSelected: '',
                      units: [],
                      unitDetails:{},
                      status: "Empty",
                      showOwn:false

                 }

             }
            async getUnitDetails(id) {
                //alert(id)
                  this.setState({unitSelected: id})
                  var DEMO_TOKEN = await AsyncStorage.getItem(Global.STORAGE_KEY);

                  fetch(Global.URL + "api/units/"+this.state.unitSelected, {
                          method: 'get',
                          dataType: 'json',
                          headers: {
                              'Accept': 'application/json',
                              'Content-Type': 'application/json',
                              'Authorization': DEMO_TOKEN
                         },
                     }).then((response) =>{
                          //alert(JSON.stringify(response))
                          return response.json() //<<This is the problem
                     }).then(function(data) {
                          //alert(JSON.stringify(data,null,4))

                          /*const tempNames = [];

                          for (var i = 0; i<data.length; i++) {
                              tempNames.push(data[i]);
                         }
                          this.setState({
                              payments: tempNames,
                              dataSource2: ds.cloneWithRows(data)
                         });
          */
                          this.setState({
                              unitDetails:data,
                              timePassed: true
                         });


                     }.bind(this)).catch(function(err) {
                          alert("Error is" + err)

                          console.log(err);
                     })
                      .done();

             }
            async startingPage() {
                //alert(this.state.unitSelected)
                  //this.setState({unitSelected: id})
                  var DEMO_TOKEN = await AsyncStorage.getItem(Global.STORAGE_KEY);

                  fetch(Global.URL + "api/units/"+this.state.unitSelected, {
                          method: 'get',
                          dataType: 'json',
                          headers: {
                              'Accept': 'application/json',
                              'Content-Type': 'application/json',
                              'Authorization': DEMO_TOKEN
                         },
                     }).then((response) =>{
                          //alert(JSON.stringify(response))
                          return response.json() //<<This is the problem
                     }).then(function(data) {
                          alert(JSON.stringify(data,null,4))
                          /*const tempNames = [];

                          for (var i = 0; i<data.length; i++) {
                              tempNames.push(data[i]);
                         }
                          this.setState({
                              payments: tempNames,
                              dataSource2: ds.cloneWithRows(data)
                         });
          */
                          this.setState({
                              unitDetails:data,
                              timePassed: true
                         });
                          if(data.status==1){
                            this.setState({status:"Empty"})
                          }
                          if(data.status==2){
                            this.setState({status:"Occupied"})
                          }
                          if(data.status==1){
                            this.setState({status:"Rented"})
                          }


                     }.bind(this)).catch(function(err) {
                          //alert("Error is" + err)

                          console.log(err);
                     })
                      .done();

             }
              componentWillMount() {
                  setTimeout((function(){
                    this.setState({timePassed:true})
                  }).bind(this),3000)
             }
              componentDidMount() {
                this.setState({units:Global.user.unitids})
                this.getUnitDetails(Global.user.unitids[0])


             }

              renderLoadingView() {
                  return ( 
                 <View style={styles.container}>
                     <Text style={{fontSize: 20}}>
                              Loading...</Text>
                 </View>
                  );
             }
             showOwner(){
              if(this.state.showOwn){
                return(
                    <View>

                                    <Text style={{fontSize: 20,color:'black'}}><Text style={{fontWeight:'bold'}}> Owner:-</Text> {this.state.unitDetails.owner.name}</Text>

                                    <Text style={{fontSize: 20,color:'black'}}><Text style={{fontWeight:'bold'}}> Status:-</Text> {this.state.status}</Text>

                    </View>
                  )
              }
             }
              renderScene(route, navigator) {
                  //alert(JSON.stringify(this.state.payments,null,4))
                  if (!this.state.timePassed) {

                      return this.renderLoadingView()
                 }


                              return ( 
                 <ScrollView>
                     <View style={styles.strip}>
                         <Image style={{width: 50, height: 30, padding: 10, top: 5}} source={require( './drawable/drawable/asap.png')} />
                         <Text style={{fontSize: 20, color: 'white', bottom: 20, left: 60, padding: 10}}>Approvals</Text>
                     </View>
                     <View>
                         <View style={{top: 50}}>
                             <View>
                                 <Tabs selected={this.state.page} style={styles.tabbar} selectedStyle={styles.tabbarSelected} onSelect={el=>this.setState({page: el.props.name})}>
                                     <Text style={{fontSize: 20}} name="Approvals">Approvals</Text>
                                     <Text style={{fontSize: 20}} name="Payments">Payments</Text>
                                 </Tabs>
                             </View>
                             <ScrollView style={{paddingBottom: 70}}>
                                   <Picker selectedValue={this.state.unitSelected}
                                    style={{width:200, left:100,bottom: 10}}
                                        label="Select Unit"
                                             onValueChange={(selectedUnit) => this.getUnitDetails(selectedUnit)}>
                                            {this.state.units.map((s, i) => {
                                                return <Picker.Item key={i} value={s} label={s}/>
                                            })}
                                    </Picker>
                                    <View style={styles.separator} />
                                    <TouchableHighlight style={{flex:1, backgroundColor:'powderblue'}} onPress={this._onPressButtonOwner()}>
                                          <Text style={{fontSize: 20,color:'black'}}>Owner Details</Text>
                                    </TouchableHighlight>
                                    {this.showOwner()}
                             </ScrollView>

                         </View>
                     </View>
                 </ScrollView>
                  );
             }


              _onPressButtonOwner() {
                alert("Button")
                  this.setState({showOwn:!this.state.showOwn})
             }

              render() {
                  return ( 
                 <Navigator renderScene={this.renderScene.bind(this)} navigator={this.props.navigator} />
                  );


             }
          }
          const styles = StyleSheet.create({
            separator: {
                  height: 2,
                  backgroundColor: 'black'
             },
              strip: {
                  width: width1,
                  height: 50,
                  backgroundColor: 'grey'

             },

              input: {
                  height: 50,
                  flex: 1,
                  paddingHorizontal: 8,
                  fontSize: 15,
                  backgroundColor: '#FFFFFF',

             }
          })

Expected Results

I should get the view in shoOwner() function after clicking on TouchableHighlight "Owner Details".

Additional Information

  • React Native version: [o.25.0-rc]
  • Platform(s) (iOS, Android, or both?): [Android]
  • Operating System (macOS, Linux, or Windows?): [Windows]
AsyncStorage Locked

Most helpful comment

I had the same issue as well. I fixed it after reading this comment, but actually tried the following instead because I needed to have parameters passed to my function... and it worked this.onPress={this._onPressButtonOwner.bind(null, parameterOneExample, this.state.parameterTwo}

All 3 comments

You are calling the onPress function in the TouchableHighlight component. onPress={this._onPressButtonOwner()} which is setting state, which is calling render, which in turn is calling the function again ad infinitum. lose the brackets such that you end up with onPress={this._onPressButtonOwner}

@ggordan Great sir, thanks a lot my issue is resolved. Thanks for your help.

I had the same issue as well. I fixed it after reading this comment, but actually tried the following instead because I needed to have parameters passed to my function... and it worked this.onPress={this._onPressButtonOwner.bind(null, parameterOneExample, this.state.parameterTwo}

Was this page helpful?
0 / 5 - 0 ratings