Undefined 不是评估 this.state/this.props 的对象

Undefined is not an object evaluating this.state/this.props

如何在 React Native 中绑定作用域外的函数?我收到错误:

undefined is not an object evaluating this.state   

&

undefined is not an object evaluating this.props

我正在使用 render 方法在数据加载后调用 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>
    )
}};

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

不确定这是否是问题所在,但我认为是代码有误,可能会导致您的问题。

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

发生这种情况是因为 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>
      );
    });
  }

Also, once you've used arrow functions in the class function definition you don't need to bind them in constructor like:

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

Also, once you have defined class functions as arrow functions, you don't need to use the arrow functions while calling them either:

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()} />
    )
  }
}

this.props are read-only

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 绑定到它。