未定义不是评估this.state/this.props的对象



我如何在React天然中的范围之外绑定一个函数?我会遇到错误:

undefined is not an object evaluating this.state   

&

undefined is not an object evaluating this.props

加载数据后,我正在使用渲染方法唤起renderGPSDataFromServer()。问题是,我正在尝试在renderGPSDataFromServer()内使用_buttonPress()calcRow(),但是我会遇到这些错误。

我添加了

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>
    )
}};

我该如何解决此问题,在这种情况下,问题是什么?

this.props是只读的

react docs-组件和props

因此,组件不应尝试修改它们,更不用说在这里进行突变:

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

我建议使用状态:

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

关于您的约束性问题:

.map方法采用第二个参数,用于在调用回调时设置this的值。

在问题的上下文中,您只需要将this作为第二个参数将其传递给您的.map方法即可将组件范围的this绑定到它。

这正在发生,因为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()} />
    )
  }
}

不确定这是否是问题,但我认为代码是错误的,并且可能导致您的问题。

<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。

您要朝着正确的方向前进,但是仍然存在一个小问题。您将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>
    )
  }};

最新更新