Display data from API Database with FlatList - javascript

export class Diet extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
fullData: [],
loading: false,
error: null,
query: "",
};
}
async componentDidMount() {
this.requestAPIFood();
}
requestAPIFood = _.debounce(() => {
this.setState({ loading: true });
const apiURL =
"https://api.edamam.com/api/food-database/v2/nutrients?app_id=${########}&app_key=${#######}";
fetch(apiURL)
.then((res) => res.json())
.then((resJson) => {
this.setState({
loading: false,
data: resJson,
fullData: resJson,
});
})
.catch((error) => {
this.setState({ error, loading: false });
});
}, 250);
renderFooter = () => {
if (!this.state.loading) return null;
return (
<View
style={{ paddingVertical: 20, borderTopWidth: 1, borderColor: "red" }}
>
<ActivityIndicator animating size="large" />
</View>
);
};
_renderItem = ({ item, index }) => {
return (
<TouchableOpacity style={{ height: hp("5%") }}>
<Text style={{ left: wp("1%") }}>{item.food}</Text>
</TouchableOpacity>
);
};
handleSearch = (text) => {
const data = _.filter(this.state.fullData);
this.setState({ data, query: text });
};
render() {
return (
<SearchBar
placeholder="Search Food..."
onChangeText={this.handleSearch}
value={data}
/>
<List >
<FlatList
data={this.state.data}
renderItem={this._renderItem}
keyExtractor={(item, index) => index.toString()}
ListFooterComponent={this.renderFooter}
/>
</List>
Good evening, I'm working on a SearchBar component to search food from the API database of Edamam (this is the link to the documentation: https://developer.edamam.com/food-database-api-docs) and display the result on a FlatList as you can see above, but when I start typing nothing will appear and I really can't seem to find the error.

Related

Make Flatlist asynchrone react native

I have an flatlist which isn't asynchrone so if i update something in my view i have to go back to the home screen and re-enter to check the modifications or save my project , i have implemented async and await in my fetch but still nothing happens !
Here is my code if someone could help me with this issue i'll appreciate it
class listDépenses extends React.Component{
constructor(props) {
super(props);
this.delayValue = 8000;
this.state = {
search:'',
dataSource: [],
animatedValue: new Animated.Value(0),
Montant:'',
Titre:'',
isLoading:true,
modalVisible:false,
}
this.arrayholder=[]
}
onPresino(item){
this.props.navigation.navigate(
'supprimerDépense',
{item})}
renderSeparator =() => {
return(
<View style={{height:1,width:'100%',backgroundColor:'#ccc'}}>
</View>
)}
renderItem = ({item}) => {
this.delayValue = this.delayValue + 500;
const translateX = this.state.animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [this.delayValue,1]
});
return(
<Animated.View
style={[styles.button, { transform: [{ translateX }] }]}
>
<View style={{flex:1,}}>
<View style={{flexDirection:'row',padding:10,flex:1}}>
<Avatar.Image
source={{
uri:uri
size={50}
/>
<Text style={[globalStyles.sousTitre,{marginVertical:10,marginLeft:10}]}>{item.Titre}</Text>
<Text style={[globalStyles.sousTitre,
{marginVertical:10,marginLeft:40,textAlignVertical:'auto',opacity:0.8,fontWeight:'800'}]}>
{item.Montant}
</Text>
<View style={{flex:1,alignItems:'flex-end',marginVertical:10}}>
<TouchableOpacity
onPress={()=> this.onPresino(item)}>
<Image
style={{ marginRight:50}}
source={require('../img/corbeille.png')}
/>
</TouchableOpacity>
</View>
</View>
</View>
</Animated.View>
)}
async componentDidMount() {
Animated.spring(this.state.animatedValue, {
toValue: 1,
tension: 20,
useNativeDriver: true
}).start();
return await fetch('http://localhost:8080/api/depenses')
.then((response )=> response.json())
.then(responseJson => {
this.setState({
dataSource: responseJson,
isLoading: false,},
function() {
this.arrayholder = responseJson;
});})
.catch(error => { console.error(error);
});
}
search = text => { console.log(text);
};
clear = () => { this.search.clear();
};
SearchFilterFunction(text) {
const newData = this.arrayholder.filter(function(item) { const itemData = item.Titre ?
item.Titre.toUpperCase() :
''.toUpperCase();
const textData = text.toUpperCase(); return itemData.indexOf(textData) > -1;
});
this.setState({ dataSource: newData, search: text,
});
}
remove= async ()=>{
const _id=this.props.route.params.item._id;
const apiUrl='http://192.168.1.10:8080/api/depenses';
Alert.alert(
//title
'Confirmez votre choix',
//body
'Voulez-vous vraiment supprimer cet article?',
[
{
text: 'Confirmer',
onPress: () => fetch(apiUrl + "/" + _id, {
method: 'DELETE',
mode:'no-cors',
}).then(() => {
Alert.alert(
"Message de confirmation",
"Dépense supprimée.",
[
{ text: "OK", onPress: () => this.props.navigation.navigate('listDépenses') }
]
); }).catch(err => {
console.error(err)})},
{
text: 'Annuler',
onPress: () => console.log('Cancel'), style: 'cancel'},],
{cancelable: false},
//clicking out side of alert will not cancel);}
render(){
if (this.state.isLoading) { return (
<View style={{ flex: 1, paddingTop: 21 }}>
<ActivityIndicator />
</View>
);
}
return (
<View style={styles.container}>
<SearchBar
round="default"
lightTheme="default"
searchIcon={{ size: 25 }}
onChangeText={text => this.SearchFilterFunction(text)} onClear={text =>
this.SearchFilterFunction('')} placeholder="Tapez ici pour chercher..." value=
{this.state.search}
/>
<View style={{marginBottom:10}}></View>
<FlatList
data={this.state.dataSource}
renderItem={this.renderItem}
keyExtractor={(item, index) => index.toString()}
enableEmptySections={true} style={{ marginTop: 11 }}
ItemSeparatorComponent={this.renderSeparator}
/>
</View>
)}}
I've found the solution if anyone need it :
You just have to implement a function that reloads data:
displayData(){
return fetch('http://localhost:8080/api/depenses')
.then((response )=> response.json())
.then(responseJson => {
this.setState({
dataSource: responseJson,
isLoading: false,
},
function() {
this.arrayholder = responseJson;
});})
.catch(error => { console.error(error);
});
}
componentDidUpdate()
{
this.displayData()
}
componentDidMount() {
this.getData();
Animated.spring(this.state.animatedValue, {
toValue: 1,
tension: 20,
useNativeDriver: true
}).start();
this.displayData()
}
and this is the function :
getData = async () => {
const apiUrl='http://localhost:8080/api/depenses';
await fetch(apiUrl,{
method:'get',
mode:'no-cors',
headers:{
'Accept':'application/json',
'Content-Type':'application/json'
}
})
.then((response) => response.json())
.then((responseJson) => {
this.setState({
dataSource:responseJson
})
})
.catch((error) =>{
console.log(error)
})
}

Implementing searchbar into flatlist to search api data react native

I've implemented an searchbar as a header of a flatlist which displays my api data (the flatlist works fine ) but the searchbar don't work , i've tried several codes but stills not working
If someone can help me with this i'll appreciate it :)
My API displays an document which contains :
-Titre(String)
-Montant(Number)
I want to search by Titre .
Here's the last code that i've tried :
class listDépenses extends React.Component{
constructor() {
super();
this.state = {
refreshing: true,
dataSource: [],
Montant:'',
Titre:'',
modalVisible:false,
loading: false,
data: [],
error: null,
}
this.arrayholder = [];
}
renderItem = ({item}) => {
<View style={{flex:1}}>
<Text style={[globalStyles.sousTitre,{marginVertical:10,marginLeft:10}]}>{item.Titre}</Text>
<Text style={[globalStyles.sousTitre,
{marginVertical:10,marginLeft:40,textAlignVertical:'auto',opacity:0.8,fontWeight:'800'}]}>
{item.Montant}</Text>
</View>}
searchFilterFunction = text => {
const newData = this.arrayholder.filter(item => {
const itemData = `${item.Titre.toUpperCase()}`;
const textData = text.toUpperCase();
return itemData.indexOf(textData) > -1;
});
renderHeader = () => {
return(
<SearchBar
placeholder="Tapez ici..."
onChangeText={text => this.searchFilterFunction(text)}
round="default"
lightTheme="default"
/>
)
}
this.setState({ data: newData });
};
async componentDidMount() {
await fetch ('http://192.168.1.10:8080/api/depenses',{
method:'get',
mode:'no-cors',
headers:{
'Accept':'application/json',
'Content-Type':'application/json'
}})
.then((response) => response.json())
.then((responseJson) => {
this.setState({
dataSource:responseJson,
data: responseJson.results,
loading: false,
})
this.arrayholder = responseJson.results;
})
.catch((error) =>{
console.log(error)
})}
render(){
return (
<View style={{flex:1}}>
<View style={{marginBottom:10}}></View>
<FlatList
data={this.state.dataSource}
renderItem={this.renderItem}
keyExtractor={(item, index) => index}
ItemSeparatorComponent={this.renderSeparator}
ListHeaderComponent={this.renderHeader}
/>
</View>
I've found the solution if anyone need it :
class listDépenses extends React.Component{
constructor(props) {
super(props);
this.delayValue = 8000;
this.state = {
search:'',
dataSource: [],
animatedValue: new Animated.Value(0),
Montant:'',
Titre:'',
isLoading:true,
modalVisible:false,
}
this.arrayholder=[]
}
componentDidMount() {
Animated.spring(this.state.animatedValue, {
toValue: 1,
tension: 20,
useNativeDriver: true
}).start();
return fetch('http://localhost:8080/api/depenses')
.then((response )=> response.json())
.then(responseJson => {
this.setState({
dataSource: responseJson,
isLoading: false,
},
function() {
this.arrayholder = responseJson;
});})
.catch(error => { console.error(error);});}
search = text => { console.log(text);
};
clear = () => { this.search.clear();
};
SearchFilterFunction(text) {
const newData = this.arrayholder.filter(function(item) { const itemData = item.Titre
? item.Titre.toUpperCase() :
''.toUpperCase();
const textData = text.toUpperCase(); return itemData.indexOf(textData) > -1;
});
this.setState({ dataSource: newData, search: text,
});
}
render(){
if (this.state.isLoading) { return (
<View style={{ flex: 1, paddingTop: 21 }}>
<ActivityIndicator />
</View>
);
}
return (
<View style={styles.container}>
<SearchBar
round="default"
lightTheme="default"
searchIcon={{ size: 25 }}
onChangeText={text => this.SearchFilterFunction(text)} onClear={text =>
this.SearchFilterFunction('')} placeholder="Tapez ici pour chercher..." value=
{this.state.search}
/>
<View style={{marginBottom:10}}></View>
<FlatList
data={this.state.dataSource}
renderItem={this.renderItem}
keyExtractor={(item, index) => index.toString()}
enableEmptySections={true} style={{ marginTop: 11 }}
ItemSeparatorComponent={this.renderSeparator}
/>
</View>

React native how to parse from json

I am trying to parse a json file with the code below and i cant get it to work, nothing is displayed.
I wanted to display some exhibits the title and their picture.
In the processExhibit i'm trying to get the json String with info and records and then map the records.
Any help is appreciated.
import React, { Component } from 'react';
import { View, Text, FlatList, Image } from 'react-native';
import PropTypes from 'prop-types';
const processExhibit = results => {
const processed = {
info: {
next: results.info.next
},
records: results.records.map(r => ({
...r,
id: r.objectnumber
}))
};
return processed;
};
class FetchExample extends Component {
constructor (props: {}) {
super(props);
this.state = {
isLoading: true,
dataSource: []
};
}
componentDidMount () {
const url =
`https://api.harvardartmuseums.org/object?apikey=83bc8170-51ae-11ea-ac7c-97706fd5f723` +
`&fields=objectnumber,dated,century,division,primaryimageurl,title` +
`&sort=totalpageviews` +
`&page=1` +
`&size=44` +
`&hasimage=1` +
`&sortorder=desc`;
fetch(url)
.then((response) => response.json())
.then((responseJson) => {
const results = processExhibit(responseJson);
this.setState({
isLoading: false,
dataSource: results
});
results = processExhibit(responseJson);
console.log("Before Change", JSON.parse(JSON.stringify(result)));
});
}
renderItem = ({item, index}) => {
let { info, records } = item;
if (!records[0]) return null;
let details = records[0];
return (
<View >
<View >
<Text >{details.title}</Text>
<Text >{details.century}</Text>
</View>
<View >
<View >
<Text >{ details.dated }</Text>
</View>
<View style={{ justifyContent: 'center', alignItems: 'center' }}>
<Image source={{uri: details.primaryimageurl}}
style={{height: 50, width: 50}}/>
</View>
</View>
</View>
);
}
keyExtractor = (item, index) => {
return index.toString();
}
render () {
return (
<View style={{flex: 1}}>
<FlatList
data={this.state.dataSource}
keyExtractor={this.keyExtractor}
renderItem={this.renderItem}
/>
</View>
);
}
}
And this is the json
info: {
next:
"https://api.harvardartmuseums.org/object?apikey=a40093f0-53ec-11ea-850a-fbf5bb8990ef&fields=objectnumber%2Cdated%2Ccentury%2Cdivision%2Cprimaryimageurl%2Ctitle&sort=totalpageviews&page=2&size=44&hasimage=1&sortorder=desc",
page: 1,
pages: 4794,
totalrecords: 210916,
totalrecordsperquery: 44
},
records: [
{
century: "19th century",
dated: "1888",
division: "European and American Art",
id: 299843,
imagepermissionlevel: 0,
objectnumber: "1951.65",
primaryimageurl: "https://nrs.harvard.edu/urn-3:HUAM:DDC251942_dynmc",
title: "Self-Portrait Dedicated to Paul Gauguin"
},
{
century: "19th century",
dated: "1877",
division: "European and American Art",
id: 228649,
imagepermissionlevel: 0,
objectnumber: "1951.53",
primaryimageurl: "https://nrs.harvard.edu/urn-3:HUAM:DDC231456_dynmc",
title: "The Gare Saint-Lazare: Arrival of a Train"
}
]
UPDATE
componentDidMount () {
const url =
`https://api.harvardartmuseums.org/object?apikey=83bc8170-51ae-11ea-ac7c-97706fd5f723` +
`&fields=objectnumber,dated,century,division,primaryimageurl,title` +
`&sort=totalpageviews` +
`&page=1` +
`&size=44` +
`&hasimage=1` +
`&sortorder=desc`;
fetch(url)
.then((response) => response.json())
.then((responseJson) => {
let results = processExhibit(responseJson);
this.setState({
isLoading: false,
dataSource: results
});
console.log("Before Change", JSON.parse(JSON.stringify(result)));
});
}
render () {
console.log('data: ', JSON.stringify(this.state.dataSource))
return (
<View style={{flex: 1}}>
<FlatList
data={[this.state.dataSource]}
renderItem={this.renderItem}
keyExtractor={this.keyExtractor}
/>
</View>
);
}

React Native List Footer Component does not work

I'm working on React native. I'm using FlatList. I want to show the loading bar as I go down. I wrote the code for that.
I've reviewed the documentation, but it's not working. I guess I'm making a mistake at the await. I don't know how to use it. What is the difference of async? I'm leaving the code sample below.
Thanks in advance for your help.
handleRefresh = () => {
this.setState({
offset: 0,
maxSize: 10,
isSearch: false,
isLoading: true,
isRefreshing: true
}, () => {
this.loadData();
});
};
handleLoadMore = () => {
this.setState({
maxSize: this.state.maxSize + 5,
isSpinner: true
}, () => {
this.loadData();
});
};
keyExtractor = (item, index) => index.toString();
renderFooter = () => {
if(this.state.isSpinner === false) { return null; }
return (
<View style={{ paddingVertical: 20 }}>
<ActivityIndicator animating size="small" />
</View>
);
};
loadData = async () => {
try {
const { offset, maxSize } = this.state;
const username = await AsyncStorage.getItem('username');
const token = await AsyncStorage.getItem('token');
var credentials = Base64.btoa(username + ':' + token);
var URL = `http://demo.espocrm.com/advanced/api/v1/Lead?sortBy=createdAt&asc&offset=${offset}&maxSize=${maxSize}`;
axios.get(URL, {headers : { 'Espo-Authorization' : credentials }})
.then(this.dataSuccess.bind(this))
.catch(this.dataFail.bind(this));
} catch (error) {
Alert.alert(
'Hata',
'Bir hata meydana geldi. Lütfen yöneticiye başvurunuz.',
[
{ text: 'Tamam', onPress: () => null }
]
);
}
};
dataSuccess(response) {
this.setState({ isRefreshing: false, isSpinner: false, isLoading: false, leadList: response.data.list });
}
dataFail(error) {
this.setState({ isLoading: false });
Alert.alert(
'Hata',
'Beklenmedik bir hata oluştu',
[
{ text: 'Tamam', onPress: () => null }
]
);
}
render() {
const { isLoading, isRefreshing, searchText, leadList } = this.state;
return(
<View style={styles.container}>
<SearchBar
placeholder="Bir lead arayın..."
onChangeText={this.searchLead.bind(this)}
onClear={this.handleRefresh}
onCancel={this.loadData}
value={searchText}
/>
{
isLoading ? <ActivityIndicator style={styles.loading} size="large" color="orange" /> :
<FlatList
data={leadList}
ListFooterComponent={this.renderFooter}
renderItem={({item}) =>
<ListItem
leftAvatar={{ source: { uri: 'https://pbs.twimg.com/profile_images/567081964402790401/p7WTZ0Ef_400x400.png' } }}
title={item.name}
subtitle={item.status}
bottomDivider={true}
/>
}
keyExtractor={this.keyExtractor}
refreshing={isRefreshing}
onRefresh={this.handleRefresh}
onEndReached={this.handleLoadMore}
onEndReachedThreshold={0.5}
/>
}
</View>
)
}
}
In your FlatList component, you need to include an attribute called extraData and set that to this.state so the component will update.
<FlatList
data={leadList}
extraData={this.state}
...
/>

How to render the response API with Flatlist in react native?

I have some issue with a Flatlist,
I need to render the response data from API in a Flatlist but it doesn't work!
but when I set the static data it works fine! and when i logging the { item } i don't show anything in Debugging! i think the syntax of Flatlist it's right!
anybody, can you help me with this issue?
mycode here
import React, { Component } from "react";
import {
StyleSheet,
Text,
View,
TextInput,
ScrollView,
Image,
ActivityIndicator,
FlatList,
ListItem
} from "react-native";
import Moment from "react-moment";
import Icon from "react-native-vector-icons/dist/FontAwesome";
export default class App extends Component {
constructor(props) {
super(props);
this.ApiKeyRef = "****";
this.watchPositionOpts = {
enableHighAccuracy: true,
timeout: 20000,
maximumAge: 1000,
distanceFilter: 5
};
this.state = {
isLoading: true,
dataSource: [],
latitude: null,
longitude: null,
error: null
};
}
componentDidMount() {
this.watchId = navigator.geolocation.watchPosition(
this.watchPositionSuccess,
this.watchPositionFail,
this.watchPositionOpts
);
}
componentWillUnmount() {
navigator.geolocation.clearWatch(this.watchId);
navigator.geolocation.stopObserving();
}
watchPositionSuccess = position => {
this.setState(
{
latitude: position.coords.latitude,
longitude: position.coords.longitude,
error: null
},
() => this.fetchCallback()
);
};
watchPositionFail = err => {
this.setState({ error: err.message });
};
fetchCallback = async () => {
const { latitude, longitude } = this.state;
const req = `http://api.openweathermap.org/data/2.5/forecast?lat=${latitude}&lon=${longitude}&units=metric&appid=${
this.ApiKeyRef
}`;
const callback = responseJson => {
// console.log(responseJson);
// console.log(responseJson.city.name);
};
await fetch(req)
.then(response => response.json())
.then(responseJson =>
this.setState({ isLoading: false, dataSource: responseJson }, () =>
callback(responseJson)
)
)
.catch(error => console.log(error));
};
render() {
const { dataSource } = this.state;
if (this.state.isLoading) {
return (
<View style={{ flex: 1, padding: 20 }}>
<ActivityIndicator />
</View>
);
}
const icon =
dataSource.list[0].main.temp <= 20
? require("./assets/cloudySun.png")
: require("./assets/sunny.png");
return (
<ScrollView style={styles.container}>
<View style={styles.head}>
<Text style={styles.titleApp}>Weather App</Text>
</View>
<View style={styles.searchSection}>
<Icon
style={styles.searchIcon}
name="search"
size={15}
color="#333"
/>
<TextInput
style={styles.input}
placeholder="Find Your City.."
underlineColorAndroid="transparent"
/>
</View>
<View style={styles.details}>
{console.log(this.state.dataSource.city.name)} // I get the City name
<FlatList
data={this.state.dataSource}
renderItem={({ item }) => (
<Text>
{item.message}, {item.city.name}
{console.log(item)} // NO Output
</Text>
)}
keyExtractor={(item, index) => index}
/>
</View>
</ScrollView>
);
}
}
Add extraData props to FlatList. extraData is used for re-render the FlatList. extraData
Maybe it will help you.
<FlatList
data={dataSource}
extraData={this.state} //for re-render the Flatlist data item
renderItem={({ item }) => (
<Text>
{item.message}, {item.city.name}
</Text>
)}
keyExtractor={(item, index) => index}
/>
convert object response to the array
await fetch(req)
.then(response => response.json())
.then(responseJson =>{
let data = [];
data.push(responseJson); //convert object response to array
this.setState({ isLoading: false, dataSource: data }, () =>
callback(data)
)}
)
.catch(error => console.log(error));
you also have to change your logic for icons in render method:
const icon =
dataSource[0].list[0].main.temp <= 20
? require("./assets/cloudySun.png")
: require("./assets/sunny.png");

Categories

Resources