2016-11-23 4 views
0

Как связать функцию за пределами области действия в React Native? Я получаю ошибки:Undefined не объект, оценивающий this.state/this.props

undefined is not an object evaluating this.state 

&

undefined is not an object evaluating this.props 

Я использую метод визуализации, чтобы вызвать renderGPSDataFromServer(), когда данные были загружены. Проблема в том, что я пытаюсь использовать _buttonPress() и calcRow() внутри renderGPSDataFromServer(), но я получаю эти ошибки.

Я добавил

constructor(props) { 
    super(props); 
    this._buttonPress = this._buttonPress.bind(this); 
    this.calcRow = this.calcRow.bind(this); 

к моему конструктору, и я изменил _buttonPress() { к _buttonPress =() => { и до сих пор ничего.

Я думаю, я понимаю эту проблему, но я не знаю, как это исправить:

renderLoadingView() { 
    return (
     <View style={[styles.cardContainer, styles.loading]}> 
      <Text style={styles.restData}> 
       Loading ... 
      </Text> 
     </View> 
    ) 
} 

_buttonPress =() => { 
    this.props.navigator.push({ 
     id: 'Main' 
    }) 
} 

renderGPSDataFromServer =() => { 
    const {loaded} = this.state; 
    const {state} = this.state; 

    return this.state.dataArr.map(function(data, i){ 
     return(
      <View style={[styles.cardContainer, styles.modularBorder, styles.basePadding]} key={i}> 
       <View style={styles.cardContentLeft}> 
        <TouchableHighlight style={styles.button} 
         onPress={this._buttonPress().bind(this)}> 
         <Text style={styles.restData}>View Video</Text> 
        </TouchableHighlight> 
       </View> 

      <View style={styles.cardContentRight}> 
      <Text style={styles.restData}>{i}</Text> 
      <View style={styles.gpsDataContainer}> 
       <Text style={styles.gpsData}> 
       {Number(data.lat).toFixed(2)}</Text> 
       <Text style={styles.gpsData}>{Number(data.long).toFixed(2)}</Text> 
      </View> 
      <Text style={styles.gpsData}> 
      {this.calcRow(55,55).bind(this)} 
      </Text> 
      </View> 
     </View> 
    ); 
    }); 
} 

render =()=> { 
    if (!this.state.loaded) { 
     return this.renderLoadingView(); 
    } 
    return(
     <View> 
     {this.renderGPSDataFromServer()} 
     </View> 
    ) 
}}; 

Как я могу идти о фиксации этого и в этом случае то, что проблема?

ответ

1

Это происходит потому, что функция внутри метода map создает другой контекст. Вы можете использовать функции стрелок как обратный вызов в методе map для лексической привязки. Это должно решить проблему, с которой вы сталкиваетесь.

renderGPSDataFromServer =() => { 
 

 
    const {loaded} = this.state; 
 
    const {state} = this.state; 
 

 
    return this.state.dataArr.map((data, i) => { 
 
     return(
 
     <View style={[styles.cardContainer, styles.modularBorder, styles.basePadding]} key={i}> 
 

 
      <View style={styles.cardContentLeft}> 
 
      <TouchableHighlight style={styles.button} 
 
      onPress={this._buttonPress().bind(this)}> 
 
      <Text style={styles.restData}>View Video</Text> 
 
      </TouchableHighlight> 
 
      </View> 
 

 
      <View style={styles.cardContentRight}> 
 
      <Text style={styles.restData}>{i}</Text> 
 
      <View style={styles.gpsDataContainer}> 
 
       <Text style={styles.gpsData}> 
 
       {Number(data.lat).toFixed(2)}</Text> 
 
       <Text style={styles.gpsData}>{Number(data.long).toFixed(2)}</Text> 
 
      </View> 
 
      <Text style={styles.gpsData}> 
 
      {this.calcRow(55,55).bind(this)} 
 
      </Text> 
 
      </View> 
 

 
     </View> 
 
    ); 
 
    }); 
 
    }

Кроме того, как только вы использовали функцию стрелок в определении функции класса вы не нужно связывать их в конструкторе, как:

constructor(props) { 
 
    super(props); 
 
    this._customMethodDefinedUsingFatArrow = this._customMethodDefinedUsingFatArrow.bind(this) 
 
}

Кроме того, как только вы определили функции класса как функции со стрелками, вы не нужно использовать функции со стрелками, называя их либо:

class Example extends React.Component { 
 
    myfunc =() => { 
 
    this.nextFunc() 
 
    } 
 

 
    nextFunc =() => { 
 
    console.log('hello hello') 
 
    } 
 

 
    render() { 
 
    // this will give you the desired result 
 
    return (
 
     <TouchableOpacity onPress={this.myFunc} /> 
 
    ) 
 
    
 
    // you don't need to do this 
 
    return (
 
     <TouchableOpacity onPress={() => this.myFunc()} /> 
 
    ) 
 
    } 
 
}

0

не уверен, если это проблема, но я думаю, что код неправильный и может потенциально вызвать вашу проблему.

<View style={styles.cardContentLeft}> 
    <TouchableHighlight style={styles.button} 
    onPress={this._buttonPress().bind(this)}> 
    <Text style={styles.restData}>View Video</Text> 
    </TouchableHighlight> 
</View> 

конкретно эта линия onPress={this._buttonPress().bind(this)}> вы вызываете функцию и связывание его в то же время.

правильный способ сделать это было бы так

onPress={this._buttonPress.bind(this)}> 

таким образом функция будет вызываться только onPress.

0

Вы идете в правильном направлении, но есть еще незначительная проблема. Вы передаете function на ваш обратный вызов map, который имеет разную область (this), чем ваш компонент (потому что это не функция стрелки), поэтому, когда вы делаете bind(this), вы отменяете свой обратный вызов, чтобы использовать область действия от map. Я думаю, что это должно работать, оно в основном превращает обратный вызов, который вы передаете в map в функцию стрелки. Кроме того, поскольку вы bind ваша функция в конструкторе, вам не нужно делать это снова:

// The constructor logic remains the same 
    // .... 
    renderLoadingView() { 
     return (
     <View style={[styles.cardContainer, styles.loading]}> 
     <Text style={styles.restData}> 
      Loading ... 
     </Text> 
     </View> 
    ) 
    } 

    _buttonPress =() => { 
     this.props.navigator.push({ 
     id: 'Main' 
     }) 
    } 

    renderGPSDataFromServer =() => { 

    const {loaded} = this.state; 
    const {state} = this.state; 

    return this.state.dataArr.map((data, i) => { 
     return(
     <View style={[styles.cardContainer, styles.modularBorder, styles.basePadding]} key={i}> 

      <View style={styles.cardContentLeft}> 
      <TouchableHighlight style={styles.button} 
      onPress={this._buttonPress}> 
      <Text style={styles.restData}>View Video</Text> 
      </TouchableHighlight> 
      </View> 

      <View style={styles.cardContentRight}> 
      <Text style={styles.restData}>{i}</Text> 
      <View style={styles.gpsDataContainer}> 
       <Text style={styles.gpsData}> 
       {Number(data.lat).toFixed(2)}</Text> 
       <Text style={styles.gpsData}>{Number(data.long).toFixed(2)}</Text> 
      </View> 
      <Text style={styles.gpsData}> 
      {this.calcRow(55,55).bind(this)} 
      </Text> 
      </View> 

     </View> 
    ); 
    }); 
    } 

    render =()=> { 
    if (!this.state.loaded) { 
     return this.renderLoadingView(); 
    } 
    return(
     <View> 
     {this.renderGPSDataFromServer()} 
     </View> 
    ) 
    }}; 
+1

Я также думаю, что вы должны следовать совету Пинеды о том, как бороться с реквизитом, я полностью игнорировал это в своем ответе. – martinarroyo

2

this.props доступны только для чтения

React docs - component and props

И поэтому компонент не должен попробовать изменить их не говоря уже мутировать их, как вы делаете здесь:

_buttonPress =() => { 
     this.props.navigator.push({ 
     id: 'Main' 
     }) 
    } 

я предлагаю использовать вместо состояния:

_buttonPress =() => { 
    this.setState = { 
    ...this.state, 
    navigator: { 
     ...this.state.navigator, 
     id: 'Main' 
    } 
    } 
} 

Относительно вашей проблемы с привязкой:

.map принимает второй аргумент, который используется для установки значения this при вызове обратного вызова.

В контексте вашего вопроса вам просто нужно передать this в качестве второго аргумента вам .map метод привязки области видимости области this к ней.

Смежные вопросы