Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React-Native: Cannot access state values or any methods declared from renderRow

I have a listview, whenever user clicks on an item, i want to do something with onPress (touchable highlight).

I tried defining function then calling them in onPress but they didnt work.

first i defined a function like this :

constructor(props) {
        super(props);
        this.state = {
          dataSource: new ListView.DataSource({
            rowHasChanged: (row1, row2) => row1 !== row2,
          }),
          loaded: false,
        };
        this._dosome = this._dosome.bind(this);
    }

    _dosome(dd){
      console.log(dd);
    }

Then :

render(){
  if (!this.state.loaded) {
      return this.renderLoadingView();
    }

    return (
      <View style={{
        flex: 1
      }}>
      <ListView
        dataSource={this.state.dataSource}
        renderRow={this.renderRow}
        style={styles.listView}
      />
      </View>
    );
  }

  renderRow(data) {

    var header = (
      <View>
          <View style={styles.rowContainer}>
            <View  style={styles.textContainer}>
              <Text style={styles.title}>{data.nid}</Text>
              <Text style={styles.description} numberOfLines={0}>{data.title}</Text>
            </View>
          </View>
          <View style={styles.separator}></View>
    </View>
    );
///////////
    var cid = [];
    var content = [];
    for(let x=0; x < Object.keys(data.course).length; x++){
      cid[x] = data.course[x].course_id;
      content.push(
        <TouchableHighlight
        underlayColor='#e3e0d7'
        key={x}
        onPress={ this._dosome } //// **** PROBLEM HERE ****
        style={styles.child}
        >
        <Text style={styles.child}>
        {data.course[x].title}
        </Text>
        </TouchableHighlight>
      );
    }
    console.log(cid);
    var clist = (
      <View style={styles.rowContainer}>
      {content}
      </View>
    );
////////////
    return (
      <Accordion
        header={header}
        content={clist}
        easing="easeOutCubic"
      />
    );
  }


  renderLoadingView() {
    return (
      <View style={styles.loading}>
        <Text style={styles.loading}>
          Loading Courses, please wait...
        </Text>
      </View>
    );
  }
}

But it didnt worked, error :

TypeError: Cannot read property '_dosome' of null(…)

I tried calling it onPress like this :

onPress={ this._dosome.bind(this) }

didn't help

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

didn't help

onPress={ console.log(this.state.loaded)}

even i cannot even access props defined in constructor. it don't know what is "this" !

I tried to define the function other way like this :

var _dosome = (dd) => {
      console.log(dd);
    };

I tried defining the _dosome before render, after render, inside render, inside renderRow, and after renderRow. all same results.

I did check lots of tutorials, lots of sample apps on rnplay, lots of threads in stackoverflow, lots of examples, but none of them worked for me. any solutions/ideas? Any help is highly appreciated. i'm struggling with this issue for 2 days now. Thanks in Advance!

like image 649
Ata Mohammadi Avatar asked Jul 08 '16 09:07

Ata Mohammadi


1 Answers

How to solve your problem

Change

  <ListView
    dataSource={this.state.dataSource}
    renderRow={this.renderRow}
    style={styles.listView}
  />

To

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

Or

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

Why?

As you already know(since you are trying to solve the problem by using arrow function and bind), to call renderRow, the caller should be in the same context as the component itself.
But this connection is lost in renderRow={this.renderRow}, which created a new function(new context).

like image 168
David Guan Avatar answered Oct 23 '22 14:10

David Guan