Currently I am trying to show the data served by an API and brought with fetch. But when deploying with FlatList I have the error:
"undefined is not an object (evaluating item.title)".
I have used JSON.stringify ()
and json.parse
, I have also stopped using both and nothing, in any way it works. Please help.
The current code is this:
const { height, width } = Dimensions.get('window');
var autorization = 'Basic asdfasdfasdf';
let url = 'https://www.pagetest/api/search';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
words: 'anyword',
Loader: [],
loadFlatList: false
}
}
handlePress = async () => {
fetch(url, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json; charset=utf-8',
'Authorization': autorization
},
body: JSON.stringify({
keyword: this.state.words,
})
})
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
Loader: responseJson.movies,
})
})
.catch((error) => {
alert(error);
})
.done();
}
/** Function that collects the text of onChangeText and makes changes in the states,
also calls the function that contains the 'fetch' **/
handleSearch = (text) => {
this.setState({ words: text, isLoading: false, loadFlatList: true });
/** Function that initiates the 'fet... */
this.handlePress();
}
render() {
return (
/** Head icons a input search **/
<View style={{ backgroundColor: '#181818', height: height }}>
<View style={styles.containerHead}>
<Image
source={BACK_ICON}
style={{ width: 40, height: 40, paddingRight: 3,
paddingTop: 5 }} />
<View style={styles.containerFrom}>
<Image
source={SEARCH_ICON}
style={{ width: height * .02, height: height
* .02, opacity: .2 }} />
<TextInput style={styles.txtInput} placeholder=
{'Searching'}
onChangeText={(text) =>
this.handleSearch(text)}
></TextInput>
</View>
</View>
{this.state.isLoading &&
<View style={styles.bodyText}>
<Text style={styles.titleText}>
Find movies, series, directors, actors and...
</Text>
</View>}
/** Here the FlatList starts... */
<View style={styles.bodyText}>
<ScrollView>
{this.state.Loader.length > 0 && <FlatList
data={this.state.Loader}
keyExtractor={(item) => item}
extraData={this.state}
renderItem={({ item }) => <View style={styles.bodyText}>
<Text style={styles.titleText}>{item.title}, {item.description}</Text>
</View>}
/>}
</ScrollView>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
titleText: {
fontSize: 25,
color: '#fff',
justifyContent: 'center',
alignItems: 'center',
alignContent: 'center',
},
containerHead: {
flexDirection: 'row',
backgroundColor: '#000000',
justifyContent: 'space-between',
height: height * .05
},
containerFrom: {
flexDirection: 'row',
backgroundColor: '#000000',
justifyContent: 'flex-end'
},
bodyText: {
justifyContent: 'center'
},
});
I have made sure that when FlatList starts its work fetch fetched data is available in the state, for this I use {this.state.Loader>0 && ...}
but it has not worked, neither has it worked with map. The JSON that I get from the API is like this:
{
"keyword": " santo",
"movies": [
{
"id": "116",
"title": "El Milagro De Todos Los Santos",
"description": "Cuando un grupo de refugiados birmanos se une a la congregación, el pastor de una iglesia anglicana que fracasa intenta ayudarlos plantando cosechas y buscando la ayuda de la comunidad.",
"url": "https://www.pagetest.com/assets/video/705ae4c7b5e92a52cb9763ecb50b06d1.mp4",
"url_en": "",
"clasification": {
"title": "A",
"description": "Mayores de 6 años."
},
"year": "2017",
"poster": "https://www.pagetest.com/assets/global/movie_poster/116.jpg",
"thumbnail": "https://www.pagetest.com/assets/global/movie_thumb/116.jpg"
},
null
],
"series": []
}
Any idea why neither FlatList nor map()
are working here?
is because your second Item in the list is null
. Your movies array has 2 elements, the second is null
. Remove the null
from your array and should work.
renderItem={({ item }) => {
if(item !== null) {
return <View style={styles.bodyText}>
<Text style={styles.titleText}>{item.title},
{item.description}</Text>
</View>
}
}
or better just clear your array before using it
let filteredArray = arr.map((item) => {
if(item !== null) {
return item;
} else {
return false;
}
}).filter(Boolean);
I prefer the second solution .