Reputation: 15
I'm very very new to Javascript and React-Native and am building just a very simple app that can scan the barcode of a book for the ISBN and then match it to the title of the book.
I think I've managed to get the ISBN number and am trying to fetch the book title from google-books API, but I keep getting the error "undefined is not an object(evaluating '_this.state.results.items[0].title)". Can anyone help me figure out what's wrong and what steps I can take to fix it? Thank you! Sorry if there are a ton of mistakes or my code is terrible. I'm really new to this and appreciate the help!
import React from 'react';
import { Dimensions, StyleSheet, Text, View } from 'react-native';
import { BarCodeScanner } from 'expo';
const { width } = Dimensions.get('window');
export default class App extends React.Component {
constructor(props) {
super(props);
this.state= {
results: {
kind: '',
totalItems: 0,
items: []
}
}
this.fetchData = this.fetchData.bind(this);
}
fetchData(isbn) {
fetch(`https://www.googleapis.com/books/v1/volumes?
q=isbn:${encodeURIComponent(isbn)}`)
.then((response)=> response.json())
.then((responseData)=> {
this.setState({results: responseData})
});
}
_handleBarCodeRead = ({ type, data }) => {
var isbn = data;
this.fetchData(isbn)
var title = this.state.results.items[0].volumeInfo.title;
alert(`ISBN: ${isbn}, Title: ${title}`)
}
render() {
return (
<BarCodeScanner
onBarCodeRead={this._handleBarCodeRead}
style={[StyleSheet.absoluteFill, styles.container]}
>
<View style={styles.layerTop} />
<View style={styles.layerCenter}>
<View style={styles.layerLeft} />
<View style={styles.focused} />
<View style={styles.layerRight} />
</View>
<View style={styles.layerBottom} />
</BarCodeScanner>
);
}
}
Edit: So, I was missing the "isbn:" in my url, which was causing me to get incorrect book titles. I fixed that and now in the alert, I'm getting the correct book title matched with the ISBN. However, even though I'm getting the Alert, still have the same undefined is not an object (evaluating '_this.state.results.items[0].title)
Upvotes: 0
Views: 2956
Reputation: 103
You have a race condition.
The alert is happening before the setState
is executed. One way to get around this is to use a callback()
.
fetchData(isbn, callback) {
fetch(`https://www.googleapis.com/books/v1/volumes?q=isbn:${encodeURIComponent(isbn)}`)
.then(response => response.json())
.then(responseJson => {
this.setState({ bookInfo: responseJson.items[0].volumeInfo.title});
callback();
})
.catch(error => {
console.error(error);
});
}
alertInfo = () => {
var title = this.state.bookInfo;
alert(`Title: ${title} was scanned!`);
}
handleBarCodeScanned = ({ data }) => {
var isbn = data;
this.setState({ scanned: true });
this.fetchData(isbn, this.alertInfo);
};
Upvotes: 0
Reputation: 9451
It appears that you are trying to get the title
attribute in the wrong location.
Try changing to var title = this.state.results.items[0].volumeInfo.title;
Upvotes: 0