So I was making this movie browser project in which I had to fetch data from OMDb API(http://www.omdbapi.com/) and display the data in a Flatlist component.
Although I managed to display 10 results of every movie searched for(as API return 10 items on every call), I added a button that would run a function to send a request again to the API using the page parameter, fetch 10 more results and concatenate the results to the movies.
But as soon as I press the button and run the function, this error appears undefined is not an object (evaluating 'item.Title').
This is my code for the Home Component => Home.js
import React, { useState, useEffect } from 'react';
import { StyleSheet, View, Text, FlatList, TouchableHighlight, Image, Button} from 'react-native';
import { TextInput } from 'react-native-gesture-handler';
import { fetchMovies } from "../api/api";
export default class Home extends React.Component {
constructor(props) {
super(props);
this.state = {
text: "",
movies: null,
};
}
//update search text
componentDidUpdate(prevState) {
if (this.state.text !== prevState.text) {
this.getSearch(this.state.text);
}
}
//get search results from fetchMovies
getSearch = async text => {
const results = await fetchMovies(text)
this.setState({ movies: results });
};
////////////////////////////Function making API call using the page parameter///////////
//loading more movies
handleLoadMore = async() => {
try {
const page = Math.trunc(this.state.movies.length / 10) + 1;
const res = await fetchMovies(this.state.text, page);
this.setState(prevState => ({
movies: prevState.movies.concat(res.movies)
}))
}catch(err){
console.log(err.message);
}
}
//////////////////////////////////////////////////////////
//movie title and poster to render in the flatlist
movieCard = ({ item }) => {
return (
<TouchableHighlight
style={styles.movieCard}
underlayColor="white"
onPress={() => {
this.props.navigation.navigate("Details", {
title: item.title,
id: item.imdbID
});
}}
>
<View>
<Image
style={styles.movieImage}
source={ {uri: item.Poster} }
/>
<View style={{alignItems: 'center'}}>
<Text style={styles.movieTitle}>{item.Title} ({item.Year})</Text>
</View>
</View>
</TouchableHighlight>
);
};
render() {
return(
<View style={styles.container}>
<TextInput
style={styles.searchBox}
autoCorrect={false}
autoCapitalize='none'
autoFocus maxLength={45}
placeholder='Search'
onChangeText={(text) => this.setState({ text })}
value={this.state.text}
/>
{this.state.movies ?
<FlatList
style={styles.movieList}
data={this.state.movies}
renderItem={this.movieCard}
keyExtractor={item => item.Title + item.imdbID}
/>
:
<Text
style={{
alignSelf: 'center',
paddingTop: 150,
justifyContent: 'center',
color: '#8a8787',
fontStyle: 'italic' }}>
search for a movie above...
</Text>
}
<Button
onPress={this.handleLoadMore}
title="Load More"
color="#841584"
/>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 20,
backgroundColor: '#DDD',
alignItems: 'center',
},
searchBox: {
fontSize: 20,
fontWeight: '300',
padding: 10,
width: '100%',
backgroundColor: 'white',
borderRadius: 10,
marginBottom: 30
},
movieList: {
flex: 1,
marginHorizontal: 30,
},
movieCard: {
flex: 1,
margin: 5,
padding: 5,
},
movieImage: {
width: '100%',
height: 350,
borderRadius: 10,
alignSelf: 'center',
},
movieTitle: {
marginTop: 10,
fontSize: 20,
color: '#333'
}
});
This is the code for api functions => api.js
const API_KEY = "API_KEY";
//fetch search data from omdb api
export const fetchMovies = async (response, page) => {
const url = `http://www.omdbapi.com/?apikey=${API_KEY}&s=${response}`;
try {
let response = await fetch(url);
if(page) {
response = await fetch(url + `&page=${page}`)
}
const { Search } = await response.json();
return Search;
} catch (err) {
return console.log(err);
}
};
//fetch ID from omdb api
export const fetchById = async id => {
const url = `http://www.omdbapi.com/?apikey=${API_KEY}&i=${id}`;
try {
const response = await fetch(url);
const results = await response.json();
return results;
} catch (err) {
return console.log(err);
}
};
I know solution to this is probably simple but being new to react-native I am not able to figure it out.