如何在ListView的renderRow中访问`this`?

时间:2016-04-21 18:24:50

标签: javascript android listview react-native

我无法在ListView的一行内为onPress事件运行函数。我按照React Native教程尝试从那里继续。它似乎使用ES6语法风格。

这是代码的相关部分。

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 */

import React, {  
  TouchableHighlight,
  AppRegistry,
  Component,
  Image,
  ListView,
  StyleSheet,
  Text,
  View,
  Alert,
} from 'react-native';

class AwesomeProject extends Component {
  constructor(props) {
    super(props);
    this.something = this.something.bind(this); // <-- Trying this, not even sure why
    this.state = {
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      }),
      loaded: false,
    };
  }

//
//Irrelevant code here. Fetching stuff and renderLoadingView
//

  something = function(){
    console.log('something');
    Alert.alert(
      'Alert Title',
      'alertMessage',
    );
  }


  render() {
    console.log('this', this); //this is an instance of AwesomeProject
    if (!this.state.loaded) {
      return this.renderLoadingView();
    }

    return (
      <ListView
        dataSource={this.state.dataSource}
        renderRow={this.renderMovie}
        style={styles.listView}
        />
    );
  }

  renderMovie(movie) {
    console.log('Not this', this); //this is not an instance of AwesomeProject
    return (
      <TouchableHighlight onPress={() => {console.log(this); this.something()}}>
     <View style={styles.container}>
        <Image
          source={{uri: movie.posters.thumbnail}}
          style={styles.thumbnail}                    
        />
        <View style={styles.rightContainer}>
          <Text style={styles.title}

          >{movie.title}</Text>
          <Text style={styles.year}>{movie.year}</Text>
        </View>
      </View>
       </TouchableHighlight>
    );
  }
}

//
//More irrelevant code here. Styles and the 
//

AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);

我无法运行something功能。我尝试了各种语法但没有成功。问题似乎是this不是我所期望的,并且它没有定义变量something

我必须使其工作的唯一方法是在AwesomeProject类之外声明一个带有var something = function(){...}的外部变量。

something内声明时,有没有办法访问AwesomeProject?根据通量架构或其他什么,这可能是一个不好的做法吗?

2 个答案:

答案 0 :(得分:15)

原来我自己找到了解决方案,在这里:https://github.com/goatslacker/alt/issues/283#issuecomment-115391700

问题是,使用ES6语法,您没有this的自动绑定,因此您需要自己完成。

我的问题有三种可能的解决方案,我最喜欢第三种:

选项1:在通话中手动绑定

在代码上,将引用替换为{this.renderMovie} whith {this.renderMovie.bind(this)}

  render() {
    console.log('this', this); //this is an instance of AwesomeProject
    if (!this.state.loaded) {
      return this.renderLoadingView();
    }

    return (
      <ListView
        dataSource={this.state.dataSource}
        renderRow={this.renderMovie.bind(this)} //<-- change here
        style={styles.listView}
        />
    );
  }

选项2:对构造函数

进行绑定

当然,绑定正确的功能:

  constructor(props) {
    super(props);
    this.something = this.something.bind(this); // <-- Not this function
    this.renderMovie = this.renderMovie.bind(this); // <-- This function!!
    this.state = {
      dataSource: new ListView.DataSource({
        rowHasChanged: (row1, row2) => row1 !== row2,
      }),
      loaded: false,
    };
  }

选项3:使用箭头语法让他们完成工作

我最喜欢这个。您只需要使用箭头语法声明所涉及的函数,所以:

  renderMovie(movie) {
    //code here
  }

成为这个:

  renderMovie = (movie) => {
    //code here
  }

答案 1 :(得分:2)

除了https://stackoverflow.com/a/36779517/6100821

选项4:使用绑定运算符

<ListView
    dataSource={this.state.dataSource}
    renderRow={::this.renderMovie} //<-- cleaner, than bind
    style={styles.listView}
    />

小心,它只是proposal,而不是标准!