How do i get a specific value from an array-React Native - javascript

Hi I need help as to how do i get a specific value from an array in a web service i am using fetch method to get the data.It is in XML i am using a dependency to convert xml data to JSON.
import React from "react";
import {StyleSheet,View,ActivityIndicator,FlatList,Text,TouchableOpacity} from "react-native";
export default class Source extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
title: "Source Listing",
headerStyle: {backgroundColor: "#fff"},
headerTitleStyle: {textAlign: "center",flex: 1}
};
};
constructor(props) {
super(props);
this.state = {
loading: false,
items:[]
};
}
FlatListItemSeparator = () => {
return (
<View style={{
height: .5,
width:"100%",
backgroundColor:"rgba(0,0,0,0.5)",
}}
/>
);
}
renderItem=(data)=>
<TouchableOpacity style={styles.list}>
<Text style={styles.lightText}>{data.item.name}</Text>
<Text style={styles.lightText}>{data.item.email}</Text>
<Text style={styles.lightText}>{data.item.company.name}</Text>
</TouchableOpacity>
render(){
{
if(this.state.loading){
return(
<View style={styles.loader}>
<ActivityIndicator size="large" color="#0c9"/>
</View>
)}}
return(
<View style={styles.container}>
<FlatList
data= {this.state.dataSource}
ItemSeparatorComponent = {this.FlatListItemSeparator}
renderItem= {item=> this.renderItem(item)}
keyExtractor= {item=>item.id.toString()}
/>
</View>
)}
}
const parseString = require('react-native-xml2js').parseString;
fetch('http://192.168.200.133/apptak_service/apptak.asmx/Get_Item_Master')
.then(response => response.text())
.then((response) => {
parseString(response, function (err, result) {
console.log(response)
});
}).catch((err) => {
console.log('fetch', err)
this.fetchdata();
})
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff"
},
loader:{
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#fff"
},
list:{
paddingVertical: 4,
margin: 5,
backgroundColor: "#fff"
}
});
I am pretty new to react native and development in general i would highly apprecitate any help .I need to seprate the elements and display specific elements in the app.

As far as I can tell from your code, you are not passing the fetched data into your state. You're only logging it in the console:
parseString(response, function (err, result) {
console.log(response)
});
I think you should add the following pieces to your component:
1 . First of all set up the function to be called in your constructor, so it can access the state:
constructor(props) {
super(props);
this.state = {
loading: false,
items:[]
};
this.fetchRequest = this.fetchRequest.bind(this)
}
Create the actual function inside render:
fetchRequest() {
fetch('http://192.168.200.133/apptak_service/apptak.asmx/Get_Item_Master')
.then(response => response.text())
.then((response) => {
parseString(response, function (err, result) {
this.setState({ items: response });
});
}).catch((err) => {
console.log('fetch', err)
})
}
You need to call the fetchRequest function. You can do that in a lifecycle method of your component:
componentDidMount() {
fetchRequest();
}
Last thing is to create your Flatlist correctly:
<FlatList
data= {this.state.items}
renderItem={({ item }) => <Item title={item.title} />}
keyExtractor= {item=>item.id.toString()}
/>
Your data source is this.state.items, and not this.state.dataSource.
Unfortunately I have no idea what your data looks like, so I don't know how the keyExtractor and <Item> should be written. What I can tell you is that you will need unique IDs for your items.
You can read more about Flatlist in the React Native docs.

Related

React native flat list not rendering items

I hope you're doing okay
I'm experiencing something weird with my react-native project, The FlatList items in some of the pages aren't displayed, even though I can see them when I console.log(json.items).
Earlier today, everything worked fine. all the pages displayed their lists as they should on my device. then I started working on a new search page on snack & I added status bar, I tested and it worked on snack before adding the new code and creating the new files in my app.
The issue I'm having now is, the list on the first page is displayed, subsequent pages after that do not show list items. including the new search page that works on snack
I'll go ahead and post my code now, the first set is for the page whose listitems are displayed correctly:
App.js
class ProfileActivity extends Component
{
// Setting up profile activity title.
static navigationOptions = ({ navigation }) =>
{
return {
title: 'Home',
headerStyle : {
backgroundColor: '#00b47a',
elevation: 0
},
headerTitleStyle: {
color: 'white'
},
cardStyle: { backgroundColor: '#fff' },
headerLeft: null,
headerRight: (
<View style={{ alignSelf: 'center', alignItems: 'center', display: 'flex', flexDirection: 'row', justifyContent: 'space-evenly'}}>
<Icon containerStyle={{ paddingRight: 10 }}
color='#fff' onPress={()=> navigation.getParam('openBottomSheet')()}
name="menu" />
<Icon containerStyle={{ paddingRight: 15 }}
color='#fff' onPress={()=> navigation.getParam('openSearchPage')()}
name="search" /></View>
)
}
};
constructor () {
super()
this.state = { toggled: false }
}
componentDidMount() {
this.props.navigation.setParams({ openBottomSheet: this.onOpenBottomSheet });
this.props.navigation.setParams({ openSearchPage: this.onOpenSearchPage });
}
onOpenBottomSheet = () => {
this.Standard.open();
}
onOpenSearchPage = () => {
this.props.navigation.navigate('sixth');
}
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<StatusBar
animated={true}
backgroundColor="#00b47a"
barStyle={'light-content'}
showHideTransition={'slide'}
hidden={false} />
<MarketList navigation={this.props.navigation} />
<RBSheet
ref={ref => {
this.Standard = ref;
}}
>
...
</RBSheet>
</View>
);
}
}
Market.js
export default class MarketList extends React.Component {
constructor(props) {
super(props)
this.state = {
items: '',
};
this.animateList = new Animated.Value(0);
}
componentDidMount() {
Animated.timing(this.animateList, {
toValue: 1,
duration: 500,
}).start();
}
render() {
const rowStyles = [
styles.itemList,
{ opacity: this.animateList },
{
transform: [
{ scale: this.animateList },
],
},
];
fetch('https://mvmarket.xyz/nativeuserapp/home.php')
.then((response) => response.json())
.then((json) => {
this.setState({
items: json.items,
})
})
.catch((error) => {
console.error(error);
});
return (
<View style={styles.container}>
<FlatList
data={this.state.items}
renderItem={({item}) => <TouchableOpacity onPress={()=>this.props.navigation.navigate("fourth",{market:item.name})}><Animated.View style={rowStyles}><View style={styles.item}><Text style={styles.market}>{item.name}</Text><Text style={styles.location}>{item.Location}</Text></View><View style={styles.go}><Icon name="arrow-right" color="#00b47a" /></View></Animated.View></TouchableOpacity>}
/>
</View>
);
}
}
This next set is for one of the pages that don't show list items
App.js
class ProductsActivity extends Component {
static navigationOptions =
{
title: 'Products',
headerStyle : {
backgroundColor: '#00b47a',
elevation: 0
},
cardStyle: { backgroundColor: '#fff' },
headerTitleStyle: {
color: 'white'
},
};
render() {
return(
<View>
<StatusBar
animated={true}
backgroundColor="#00b47a"
barStyle={'light-content'}
showHideTransition={'slide'}
hidden={false} />
<ProductsList navigation={this.props.navigation} />
</View>
);
}
}
Products.js
export default class ProductsList extends React.Component {
constructor(props) {
super(props)
this.state = {
items: '',
};
}
render() {
fetch('https://mvmarket.xyz/nativeuserapp/products.php')
.then((response) => response.json())
.then((json) => {
this.setState({
items: json.items,
})
}).catch((error) => {
console.error(error);
console.log(error);
});
return (
<View style={styles.container}>
<FlatList
data={this.state.items}
renderItem={({item}) => <TouchableOpacity onPress={()=>this.props.navigation.navigate("fifth",{market: this.props.navigation.state.params.market, type:item.type})} style={styles.itemList}><View style={styles.item}><Text style={styles.market}>{item.type}</Text></View><View style={styles.go}><Icon name="arrow-right" color="#00b47a" /></View></TouchableOpacity>}
/>
</View>
);
}
}
I'm leaving the URL there so you can confirm yourself that the data is actually fetched. Its driving me crazy, been on it for like 4 hrs.
Thank you
I think you don't really understand lifecycle methods of a React Component. It's important to understand those concepts before jumping into code. You can check here
When you put your fetch call in render, and on then you do a setState() you are making this infinitely. This happens because you are always providing new values to items.
The ideal is to have a model layer to handle those type of calls, but this is an architecture thing, to be less complex, you can use Container/Presentation pattern.
In the Container/Presentation pattern, you have a ContainerComponent which is responsible to do requests, handle callbacks, and provide data to the Presentation component, which would be responsible to just render things.
If you don't want to use this pattern, at least put this fetch call in componentDidMount method.
Thank you all for your suggestions, duly noted and appreciated.
#Witalo-Benicio #Andris-laduzans #Drew-reese
I've fixed it, by changing
class SearchMarketActivity extends Component {
static navigationOptions = {
headerShown: false,
cardStyle: {
backgroundColor: 'white'
}
}
render() {
return(
<View>
<StatusBar
animated={true}
backgroundColor="#585858"
barStyle={'light-content'}
showHideTransition={'slide'}
hidden={false} />
<SearchMarket navigation={this.props.navigation} />
</View>
)
}
}
to
class SearchMarketActivity extends Component {
static navigationOptions = {
headerShown: false,
cardStyle: {
backgroundColor: 'white'
}
}
render() {
return(
<SearchMarket navigation={this.props.navigation} />
)
}
}
After, I added the StatusBar to the <SearchMarket /> component being imported

Undefined is not an object-React Native

Hi I am new to react native i am facing this error TypeError:undefined is not an object (evaluating this.state.items)
Another problem is it is returning me the data in an array how do i display the data as a string
import React, { Component } from "react";
import {StyleSheet,View,ActivityIndicator,FlatList,Text,TouchableOpacity} from "react-native";
export default class Source extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
title: "Source Listing",
headerStyle: {backgroundColor: "#fff"},
headerTitleStyle: {textAlign: "center",flex: 1}
};
};
constructor(props) {
super(props);
this.state = {
loading: false,
items:[]
};
this.fetchRequest=this.fetchRequest.bind.this
}
FlatListItemSeparator = () => {
return (
<View style={{
height: .5,
width:"100%",
backgroundColor:"rgba(0,0,0,0.5)",
}}
/>
);
}
componentDidMount()
{
fetchRequest();
}
renderItem=(data)=>
<TouchableOpacity style={styles.list}>
<Text style={styles.lightText}>{data.item.name}</Text>
<Text style={styles.lightText}>{data.item.email}</Text>
<Text style={styles.lightText}>{data.item.company.name}</Text>
</TouchableOpacity>
render(){
<FlatList
data= {this.state.dataSource}
ItemSeparatorComponent = {this.FlatListItemSeparator}
renderItem= {item=> this.renderItem(item)}
keyExtractor= {item=>item.id.toString()}
/>
fetchRequest()
{
const parseString = require('react-native-xml2js').parseString;
fetch('http://192.168.200.133/apptak_service/apptak.asmx/Get_Item_Master')
.then(response => response.text())
.then((response) => {
parseString(response, function (err, result) {
console.log(response)
});
}).catch((err) => {
console.log('fetch', err)
this.fetchdata();
})
if(this.state.loading){
return(
<View style={styles.loader}>
<ActivityIndicator size="large" color="#0c9"/>
</View>
)}}
return(
<View style={styles.container}>
</View>
)}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff"
},
loader:{
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#fff"
},
list:{
paddingVertical: 4,
margin: 5,
backgroundColor: "#fff"
}
});
Basically what i am trying to do is to get data from webservices and display the app on the screen

How do i get specific elements from webservice

I want to get specific the first two elements from a webservice and print it to a console it is returning me 1000 items. Can anyone guide me on how I can print only the first two elements
import React from "react";
import {StyleSheet,View,ActivityIndicator,FlatList,Text,TouchableOpacity} from "react-native";
export default class Source extends React.Component {
static navigationOptions = ({ navigation }) => {
return {
title: "Source Listing",
headerStyle: {backgroundColor: "#fff"},
headerTitleStyle: {textAlign: "center",flex: 1}
};
};
constructor(props) {
super(props);
this.state = {
loading: false,
items:[]
};
}
FlatListItemSeparator = () => {
return (
<View style={{
height: .5,
width:"100%",
backgroundColor:"rgba(0,0,0,0.5)",
}}
/>
);
}
renderItem=(data)=>
<TouchableOpacity style={styles.list}>
<Text style={styles.lightText}>{data.item.name}</Text>
<Text style={styles.lightText}>{data.item.email}</Text>
<Text style={styles.lightText}>{data.item.company.name}</Text>
</TouchableOpacity>
render(){
{
if(this.state.loading){
return(
<View style={styles.loader}>
<ActivityIndicator size="large" color="#0c9"/>
</View>
)}}
return(
<View style={styles.container}>
<FlatList
data= {this.state.dataSource}
ItemSeparatorComponent = {this.FlatListItemSeparator}
renderItem= {item=> this.renderItem(item)}
keyExtractor= {item=>item.id.toString()}
/>
</View>
)}
}
const parseString = require('react-native-xml2js').parseString;
fetch('http://192.168.200.133/apptak_service/apptak.asmx/Get_Item_Master')
.then(response => response.text())
.then((response) => {
parseString(response, function (err, result) {
console.log(response[0],response[1])
});
}).catch((err) => {
console.log('fetch', err)
})
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff"
},
loader:{
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#fff"
},
list:{
paddingVertical: 4,
margin: 5,
backgroundColor: "#fff"
}
});
I want it to be print on the console then I will modify it later to display it on the app. I am struggling to get this done Please help
You are parsing the response as string. If you want to print the first two item in console, you can do it like this bellow:
fetch('http://192.168.200.133/apptak_service/apptak.asmx/Get_Item_Master')
.then((response) => {
console.log(response.data[0],response.data[1])
}).catch((err) => {
console.log('fetch', err)
})
Perhaps what you need is the result?
parseString(response, function (err, result) {
console.log(result) // not console.log(response)?
});
Using JavaScript
fetch("http://192.168.200.133/apptak_service/apptak.asmx/Get_Item_Master")
.then((r) => r.text())
.then((t) => (new window.DOMParser()).parseFromString(t, "text/xml"))
.then((d) => console.log(d))
.catch((e) => console.error(e));

undefined is not an object (evaluating 'item.Title') in React Native

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.
regarding FlatList, In docs they apparently pass lambda which returns rendered items to renderItem prop
Also your initialized state.movies is null and i think it should be an empty array
this.state = {
text: "",
movies: [],
};
<FlatList
style={styles.movieList}
data={this.state.movies}
renderItem={({item}) => this.movieCard({item})}
keyExtractor={item => item.Title + item.imdbID}

Render fetch results after button is pressed

I have a list of articles which is fetching from server(json).There will be two server calls.What I meant is now I'm listing some article title (fetching from server1) within a Card.Below that there will be an add button for copy and pasting new article links(that will be saved to a different server).So I'm trying to append this newly added articles to my existing list(just like the same in pocket app).How can I do this?I've tried something like the below.But I'm getting error , may be a little mistake please help me to figure out.Since the render should happen only after button click(for viewing newly added ones).So state will also set after that right?How can I do that?
import {article} from './data'; //json
import AddNewarticle from './AddNewarticle';
class SecondScreen extends Component {
state= {
newarticle: []
};
// request for saving newly added article
onPressSubmit(){
fetch('www.mywebsite.com',{
method: 'POST',
headers:{
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
url: this.state.url,
})
})
.then(response => response.json())
.then((responseData) => this.setState({newarticle: responseData}));
}
renderArticle(){
this.state.newarticle.message.map(newlist =>
<AddNewarticle key ={newlist.title} newlist={newlist} />
);
}
render(){
return(
<ScrollView>
{article.map(a =>
<CardSection>
<Text>
{a.title}</Text>
</CardSection>
{this.renderArticle()}
</ScrollView>
<Icon
raised
name="check"
type="feather"
color="#c1aba8"
iconStyle={{ resizeMode: "contain" }}
onPress={() => {
this.onPressSubmit();
}}
/>
);
}
Also my newarticle (json) is as follows.The response I'm getting from server after submitting new articles.
{
"message": {
"authors": [
"Zander Nethercutt"
],
"html": "<div><p name=\"c8e3\" id=\"c8e3\" class=\"graf graf--p graf--hasDropCapModel graf--hasDropCap graf--leading\">The presence of advertising in This is the power of branding.",
"title": "The Death of Advertising – Member Feature Stories – Medium"
},
"type": "success"
}
The error I'm getting is newarticle is not defined.
import React, { Component } from 'react';
import { AppRegistry, StyleSheet, ActivityIndicator, ListView, Text, View, Alert,Image, Platform } from 'react-native';
class App extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true
}
}
GetItem (flower_name) {
Alert.alert(flower_name);
}
componentDidMount() {
return fetch('https://reactnativecode.000webhostapp.com/FlowersList.php')
.then((response) => response.json())
.then((responseJson) => {
let ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.setState({
isLoading: false,
dataSource: ds.cloneWithRows(responseJson),
}, function() {
// In this block you can do something with new state.
});
})
.catch((error) => {
console.error(error);
});
}
ListViewItemSeparator = () => {
return (
<View
style={{
height: .5,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}
render() {
if (this.state.isLoading) {
return (
<View style={{flex: 1, paddingTop: 20}}>
<ActivityIndicator />
</View>
);
}
return (
<View style={styles.MainContainer}>
<ListView
dataSource={this.state.dataSource}
renderSeparator= {this.ListViewItemSeparator}
renderRow={(rowData) =>
<View style={{flex:1, flexDirection: 'row'}}>
<Image source = {{ uri: rowData.flower_image_url }} style={styles.imageViewContainer} />
<Text onPress={this.GetItem.bind(this, rowData.flower_name)} style={styles.textViewContainer} >{rowData.flower_name}</Text>
</View>
}
/>
</View>
);
}
}
const styles = StyleSheet.create({
MainContainer :{
// Setting up View inside content in Vertically center.
justifyContent: 'center',
flex:1,
margin: 5,
paddingTop: (Platform.OS === 'ios') ? 20 : 0,
},
imageViewContainer: {
width: '50%',
height: 100 ,
margin: 10,
borderRadius : 10
},
textViewContainer: {
textAlignVertical:'center',
width:'50%',
padding:20
},
tabIcon: {
width: 16,
height: 16,
}
});
AppRegistry.registerComponent('App', () => App);
export default App;

Categories