Raymond Raymond - 1 month ago 19
React JSX Question

React-Native ListView: cannot read property of undefined

I am using SQLite as the device's database. What I am trying to basically achieve is this:

1- Give a user the ability to star his favorite "data"

2- Once the data gets saved in the db, retrieve it inside another page and insert them into a listView for the user to see at any time.

But no matter how much I try, I am always getting the same error.

Cannot read property of undefined.

The code:

import React, { Component } from 'react'
import {
View,
Text,
ListView
} from 'react-native'
var SQLite = require('react-native-sqlite-storage')
var db = SQLite.openDatabase({ name: "RHPC.db", location: "default"})
var obj;

class Schedules extends Component {
constructor(props) {
super(props)

const ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
});

this.state = {
datasource: []
}

db.transaction((tx) => {
tx.executeSql("SELECT * FROM schedules", [], (tx, res) => {
let len = res.rows.length;
if(len > 0) {
for(let i = 0; i < len; i++) {
var obj = [{id: res.rows.item(i)["id"], title: res.rows.item(i)["title"]}]
}
this.setState({
datasource: obj
})
} else {
console.log("empty")
}
})
}, (err) => {
console.log("error: " + JSON.stringify(err))
})
}

_renderRow(rowData) {
return(
<View>
<Text key={rowData.id}>
{rowData.title}
</Text>
</View>
)
}

render() {
console.log(this.state.datasource);
return(
<View style={{marginTop: 150}}>
<ListView
dataSource={this.state.datasource}
renderRow={this._renderRow.bind(this)}
/>
</View>
);
}
}


const styles = {

}

export default Schedules;


When I try to console.log the dataSource state:

0: Object
id: 2
title: "Session 1: Transition from Humanitarian Assistance to Rebuilding Health & Health Systems."


So in other words it looks like it's working but not 100%? Because I do have two rows inside that table and it's only retrieving the last one. Is this the cause of the undefined issue?

Answer

You use ListView in a wrong way, you create new dataSource in constructor (ds) and not assign it anywhere, checkout example in documentation: https://facebook.github.io/react-native/docs/listview.html

It should be:

constructor(props) {
    super(props)

    this.state = {
     dataSource: new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}),
    }
}

And in setState make something like this:

this.setState({
    datasource: this.state.dataSource.cloneWithRows(obj)
})

Edit:

And in your for loop you should have:

var obj = [];
for(let i = 0; i < len; i++) {
    obj.push({id: res.rows.item(i)["id"], title: res.rows.item(i)["title"]});
}
Comments