Ataomega Ataomega - 4 months ago 57
iOS Question

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!

Answer

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 solve the problem by using arrow function and bind), to call renderRow the caller should be in same context as component itself.
But this connection is lost in renderRow={this.renderRow}, which created a new function(new context).

Comments