How to present XML in a Flat List react native - json

I have a React Native application and I want to:
Fetch data in a XML format from here
Translate it to JSON using react-native-xml2js
Display the JSON data in a FlatList
Here's my source code
import React, { useEffect, useState } from 'react';
import { SafeAreaView, FlatList, Text, View } from 'react-native';
import {parseString} from 'xml2js'
export default function App() {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
console.log(data);
useEffect(() => {
var url = "http://www.xmltv.co.uk/feed/9437"
fetch(url)
.then((response) => response.text())
.then((responseText) => {
parseString(responseText, function (err, result) {
console.log(result);
// Where do I set data? setData(responseText);
return result;
});
this.setState({
datasource : result
})
})
.catch((error) => {
console.log('Error fetching the feed: ', error);
})
.finally(() => setLoading(false));
});
return (
<SafeAreaView style={{ flex: 1, padding: 24 }}>
{isLoading ? <Text>Loading...</Text> :
( <View style={{ flex: 1, flexDirection: 'column', justifyContent: 'space-between'}}>
<FlatList
data={data.channel}
keyExtractor={({ id }, index) => id}
renderItem={({ item }) => (
<Text>{item.display-name}</Text>
)}
/>
</View>
)}
</SafeAreaView>
);
}
Here's a snippet of the JSON that's rendered using console.log(result)
Object {
"tv": Object {
"$": Object {
"generator-info-name": "xmltv.co.uk",
"source-info-name": "xmltv.co.uk",
},
"channel": Array [
Object {
"$": Object {
"id": "1475611020f8d0be2662c20838ddc555",
},
"display-name": Array [
"AMC from BT",
],
"icon": Array [
Object {
"$": Object {
"src": "/images/channels/1475611020f8d0be2662c20838ddc555.png",
},
},
],
},
}
But I'm unsure as to how I pull it into my flat list. Any help would be hugely appreciated! Thanks.

Try below code that might help:
import React, {useEffect, useState} from 'react';
import {FlatList, SafeAreaView, Text, View} from 'react-native';
import {parseString} from 'react-native-xml2js';
export default function App() {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
useEffect(() => {
var url = 'http://www.xmltv.co.uk/feed/9437';
fetch(url)
.then((response) => response.text())
.then((responseText) => {
parseString(responseText, (_, result) => {
setData(result.tv.channel);
});
})
.catch((error) => {
console.log('Error fetching the feed: ', error);
})
.finally(() => setLoading(false));
}, []);
return (
<SafeAreaView style={{flex: 1, padding: 24}}>
{isLoading ? (
<Text>Loading...</Text>
) : (
<View
style={{
flex: 1,
flexDirection: 'column',
justifyContent: 'space-between',
}}>
<FlatList
data={data ?? []}
keyExtractor={({$: {id}}, index) => id}
renderItem={({item}) => <Text>{item['display-name'][0]}</Text>}
/>
</View>
)}
</SafeAreaView>
);
}

Related

Fetch post API returning empty array in react native iphone app but working well in postman

I have a fetch API to get values from mysql database.Below is my screen code in which I need to get data from API:
TargetSetUpPage.js:
import React, {
useState,
useEffect,
useReducer,
useSelector,
Component,
} from "react";
import { StyleSheet, Text, Button, TextInput, ScrollView } from "react-native";
import * as authActions from "../../store/actions/auth";
const TargetSetUpPage = (props) => {
const [targetid, setTargetId] = React.useState("");
const onScreenLoad = () => {
let action;
action = authActions.getDeviceInfo();
};
useEffect(() => {
onScreenLoad();
});
return (
<ScrollView showsVerticalScrollIndicator={true}>
<Text style={styles.headingTitle}>
Set your target and start running:
</Text>
<Text style={styles.textstyle}>Target ID</Text>
<TextInput
style={styles.input}
value={targetid}
onChangeText={(targetid) => setTargetId(targetid)}
></TextInput>
<Button
title="Add"
// onPress = {() => }
/>
</ScrollView>
);
};
const styles = StyleSheet.create({
input: {
height: 40,
width: "80%",
margin: 12,
borderWidth: 1,
padding: 10,
},
headingTitle: {
fontSize: 30,
},
textstyle: {
paddingTop: 10,
fontSize: 20,
},
compact: {
flexDirection: "row",
},
buttonleft: {
paddingTop: 40,
height: 40,
width: "80%",
},
});
export default TargetSetUpPage;
Below is the store code which calls fetch API.
auth.js
import AsyncStorage from "#react-native-community/async-storage";
import Device from "../../model/Device";
export const LOGIN = "LOGIN";
export const LOGOUT = "LOGOUT";
export const GETDEVICEINFO = "GETDEVICEINFO";
export const login = (textemailid, textpassword) => {
const formData = new FormData();
formData.append("txtUemail", textemailid);
formData.append("txtUpass", textpassword);
return async (dispatch) => {
fetch("https://------------------------/login.php", {
method: "post",
body: formData,
})
.then((res) => res.text())
.then((loginresult) => {})
.catch((err) => {
console.log(err);
});
const saveDataToStorage = (loginresult) => {
AsyncStorage.setItem(
"userData",
JSON.stringify({
loginresult: loginresult,
})
);
};
dispatch({ type: LOGIN });
};
};
export const logout = () => {
return { type: LOGOUT };
};
export const getUserInfo = (textemailid) => {
const formData = new FormData();
formData.append("txtEmail", textemailid);
return async (dispatch) => {
fetch("https://------------------------/getUserInformation.php", {
method: "post",
body: formData,
})
.then((res) => res.json())
.then((getuseridresult) => {
const userid = getuseridresult.map((d) => d.id);
saveDataToStorage(userid);
})
.catch((err) => {
console.log(err);
});
const saveDataToStorage = async (userid) => {
try {
await AsyncStorage.setItem(
"userDatauserid",
JSON.stringify({
userid: userid,
})
);
} catch (e) {
alert("not saved");
}
};
};
};
export const getDeviceInfo = async () => {
const useridfordevices = await AsyncStorage.getItem("userDatauserid");
const obj = JSON.parse(useridfordevices);
const { userid } = obj;
var userid1 = userid[0];
console.log("txtUserId is " + userid1);
const formData = new FormData();
formData.append("txtUserId", userid1);
console.log(formData);
return async (dispatch) => {
fetch("https://-------------------------------/getDeviceInformation.php", {
method: "post",
body: formData,
})
.then((res) => res.json())
.then((result) => {
console.log("Hi" + result);
})
.catch((err) => {
console.log(err);
});
};
};
getDeviceInfo function in the above auth.js is not returning anything. I am sending correct data to fetch API as below:
txtUserId is 616718042ad26
FormData {
"_parts": Array [
Array [
"txtUserId",
"616718042ad26",
],
],
In postman I am getting the below JSON data:
[
{
"targetid": "TargetDevice1",
"targetname": "device_1",
"userid": "616718042ad26"
},
{
"targetid": "TargetDevice2",
"targetname": "device_2",
"userid": "616718042ad26"
}
]
Import and add dispatch in TargetSetUpPage:
TargetSetUpPage.js:
import React, {
useState,
useEffect,
useReducer,
useSelector,
Component,
} from "react";
import { StyleSheet, Text, Button, TextInput, ScrollView } from "react-
native";
import { useDispatch } from "react-redux";
import * as authActions from "../../store/actions/auth";
import AsyncStorage from '#react-native-community/async-storage';
const TargetSetUpPage = (props) => {
const [targetid, setTargetId] = React.useState("");
const dispatch = useDispatch();
const onScreenLoad = async() => {
const useridfordevices = await AsyncStorage.getItem("userDatauserid");
const obj = JSON.parse(useridfordevices);
const { userid } = obj;
var userid1 = userid[0];
console.log("txtUserId is " + userid1);
let action;
action = authActions.getDeviceInfo(
userid1
);
await dispatch(action);
};
useEffect(() => {
onScreenLoad();
});
return (
<ScrollView showsVerticalScrollIndicator={true}>
<Text style={styles.headingTitle}>
Set your target and start running:
</Text>
<Text style={styles.textstyle}>Target ID</Text>
<TextInput
style={styles.input}
value={targetid}
onChangeText={(targetid) => setTargetId(targetid)}
></TextInput>
<Button
title="Add"
// onPress = {() => }
/>
</ScrollView>
);
};
const styles = StyleSheet.create({
input: {
height: 40,
width: "80%",
margin: 12,
borderWidth: 1,
padding: 10,
},
headingTitle: {
fontSize: 30,
},
textstyle: {
paddingTop: 10,
fontSize: 20,
},
compact: {
flexDirection: "row",
},
buttonleft: {
paddingTop: 40,
height: 40,
width: "80%",
},
});
export default TargetSetUpPage;
In the store, dispatch the action to TargetSetUpPage.js from getDeviceInfo function.
auth.js:
export const getDeviceInfo = (userid1) => {
const formData = new FormData();
formData.append("txtUserId", userid1);
return async dispatch => {
fetch('https://----------/getDeviceInformation.php',
{
method:'post',
body: formData
})
.then((res) => res.json())
.then((getuserdeviceinfo) => {
const loadDevices = [];
loadDevices.push(
new Device(
getuserdeviceinfo.map((d) => d.targetid),
getuserdeviceinfo.map((d) => d.targetname),
)
);
console.log(loadDevices);
})
.catch((err) =>{
console.log(err);
})
dispatch({type:GETDEVICEINFO,availableDevice:loadDevices})
}
}
This displays the Device array from mysql database.
Array [
Device {
"TargetId": Array [
"jtgTargetDevice1",
"jtgTargetDevice2",
],
"TargetName": Array [
"device_1",
"device_2",
],
},
]

How to parse a JSON Response in React-Native

I have a JSON response from Django REST API like this:
[
{"email": "email1#gmail.com", "fullname": "fn1", "id": 1},
{"email": "email2#gmail.com", "fullname": "fn2", "id": 2},
{"email": "email3#gmail.com", "fullname": "fn3", "id": 3},
{"email": "email4#gmail.com", "fullname": "fn4", "id": 4},
{"email": "email5#gmail.com", "fullname": "fn5", "id": 5}
]
And I want to parse it in React native I used this code but it doesn't function for me I don't know why!
I'm a little bit new to this framework
import React , { useEffect, useState } from 'react';
import { View, ScrollView, Text,ActivityIndicator } from 'react-native';
const Information: () => React$Node = () => {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
useEffect(() => {
fetch('http://192.168.1.18:8000/api/User')
.then((response) => response.json())
.then((json) => setData(json))
.catch((error) => console.error(error))
.finally(() => setLoading(false));
}, []);
return (
<>
<ScrollView>
<View>
{isLoading ? <ActivityIndicator/> : (
<View
data={data}
renderItem={({ item }) => (
<Text >{item.id},{item.email},{item.fullname}</Text>
)}
/>
)}
</View>
</ScrollView>
</>
);
};
export default Information;
Here you have an example of FlatList:
return (
<SafeAreaView>
<FlatList
data={data}
renderItem={({ item }) => <Text>{item.email} ... and other stuff</Text>}
keyExtractor={item => item.id}
/>
</SafeAreaView>
)

How can i put the data array gained from the fetch return to the Dropdown component?

I'm trying to make a simple dropdown list which data is gained from a fetch return..
if I use console to view the return, it shows like this :
[
{
"ID": "BOGOR~10"
"Location": "BOGOR"
},
{
"ID": "JADETABEK~16"
"Location": "JADETABEK"
}
]
if I want to take the location BOGOR and JADETABEK and put them into a Dropdown, how can I do that? this is my testing class
import React , { Component } from 'react';
import { View , StyleSheet , Text , Dimensions } from 'react-native';
import { Dropdown } from 'react-native-material-dropdown';
const ScreenWidth = Dimensions.get('window').width;
const Screenheight = Dimensions.get('window').height;
export default class testing extends Component {
constructor(props) {
super(props)
this.state = {
data: []
}
}
componentDidMount() {
fetch(url , {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({"lokasi":
{
}
})
})
.then(response => response.json())
.then(res => {
this.setState({
data: res.PilihLokasiResult.Lokasi
})
alert(res.PilihLokasiResult.Lokasi)
})
}
render() {
return(
<View style={styles.container}>
<View>
<Text>{this.state.location}</Text>
<Dropdown label="select location" style={{width: 400 }}/>
</View>
</View>
)
}
}
You need to format the data since react-native-material-dropdown accepts data in the form of {value: 'Sample'}
this.state = {
data: [],
dropDownData: []
}
const formatData = (data) => {
return data.map(dataObj => {
return {value: dataObj.Location} // return based on location
})
}
.then(res => {
const dropDownData = formatData(res.PilihLokasiResult.Lokasi)
this.setState({
data: res.PilihLokasiResult.Lokasi,
dropDownData
})
})
<Dropdown label="select location" data={this.state.dropDownData} style={{width: 400 }}/>

How can I load data from a JSON file which is stored at GitHub in React Native?

I have the following JSON file in my GitHub and want to load it:
{"Cat": [
{"key": "a", "title": "Bangladesh", "image": "https://raw.githubusercontent.com/mudassir21/server/master/img/bangladesh.jpg"},
{"key": "b", "title": "Sports", "image": "https://raw.githubusercontent.com/mudassir21/server/master/img/sports.jpg"},
{"key": "c", "title": "Politics", "image": "https://raw.githubusercontent.com/mudassir21/server/master/img/politics.jpg"},
{"key": "d", "title": "Entertainment", "image": "https://raw.githubusercontent.com/mudassir21/server/master/img/entertainment.png"},
{"key": "e", "title": "Economics", "image": "https://raw.githubusercontent.com/mudassir21/server/master/img/economics.jpg"},
{"key": "f", "title": "Technology", "image": "https://raw.githubusercontent.com/mudassir21/server/master/img/technology.jpg"},
{"key": "g", "title": "Others", "image": "https://raw.githubusercontent.com/mudassir21/server/master/img/m.jpg"}
]}
I tried to use the following code to fetch it:
getMoviesFromApiAsync() {
return fetch('https://raw.githubusercontent.com/mudassir21/server/master/newsCategory.json')
.then((response) => response.json())
.then((responseJson) => {
return responseJson.Cat;
})
.catch((error) => {
console.error(error);
});
}
<FlatList horizontal= {true}
data={this.getMoviesFromApiAsync()}
renderItem={({item}) => (
<TouchableOpacity
style={styles.catOption}
onPress = { ()=> this.setState({ name: item.title })}
>
<Image
style={styles.imgButton}
source={{uri: item.image}}
/>
<Text style={styles.buttonText}>{item.title}</Text>
</TouchableOpacity>
)
}
/>
However, no data is loaded from the JSON file. What's the problem?
As your fetch is triggered when the list is rendered, the result of the fetch is not set. In order to re-render the list with data I would suggest to set the result inside the state of the Component. This will trigger a re-render and you should be able to see the list after the fetch resolves:
class MyComp extends Component {
state = { result: [] }
componentWillMount(){
this.getMoviesFromApiAsync()
}
getMoviesFromApiAsync = () => fetch('https://raw.githubusercontent.com/mudassir21/server/master/newsCategory.json')
.then((response) => response.json())
.then((responseJson) => {
this.setState({ result: responseJson.Cat });
})
.catch((error) => {
console.error(error);
})
render(){
<FlatList data={this.state.result} ... />
}
}
Read this link
Use this code:
import React, { Component } from 'react';
import { ActivityIndicator, ListView, Text, View } from 'react-native';
export default class Movies extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true
}
}
componentDidMount() {
return fetch('https://facebook.github.io/react-native/movies.json')
.then((response) => response.json())
.then((responseJson) => {
let ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.setState({
isLoading: false,
dataSource: ds.cloneWithRows(responseJson.movies),
}, function() {
// do something with new state
});
})
.catch((error) => {
console.error(error);
});
}
render() {
if (this.state.isLoading) {
return (
<View style={{flex: 1, paddingTop: 20}}>
<ActivityIndicator />
</View>
);
}
return (
<View style={{flex: 1, paddingTop: 20}}>
<ListView
dataSource={this.state.dataSource}
renderRow={(rowData) => <Text>{rowData.title}, {rowData.releaseYear}</Text>}
/>
</View>
);
}
}

React-Native Rendering json flatlist

I am new to react-native. I'm building up complexity but have gotten stuck on rendering FlatList items from a json list. This was working fine for ListView but not able to figure out what I am missing on FlatList.
import React, { Component } from 'react';
import { ActivityIndicator, ListView, Text, View, StyleSheet,TouchableOpacity, FlatList } from 'react-native';
export default class Movies extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true
}
}
componentDidMount() {
return fetch('https://gnosisdevelopment.com/office/list.json')
.then((response) => response.json())
.then((responseJson) => {
let data_source = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.setState({
isLoading: false,
dataSource: data_source.cloneWithRows(responseJson.office_staff),
}, function() {
// do something with new state
});
})
.catch((error) => {
console.error(error);
});
}
render() {
if (this.state.isLoading) {
return (
<View style={{flex: 1, paddingTop: 20}}>
<ActivityIndicator />
</View>
);
}
return (
<View style={styles.container}>
<FlatList
data={this.state.dataSource}
renderItem={({item}) =>
<Text style={styles.touchButtonText}>{item.staff_name} </Text>
}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex:1,
alignItems: 'center',
alignContent:'center',
flexDirection: 'row',
flexWrap:'wrap',
justifyContent:'center',
},
touchButton:{
alignSelf:'center',
backgroundColor:'#2980b9',
paddingVertical: 25,
width:295,
margin:15,
},
touchButtonText:{
textAlign:'center',
color:'#ffffff',
fontWeight:'bold'
},
})
The text field will be in a touchable and I'll be adding function to the buttons but I wanted to get the listing correct first.
Any suggestions are welcome. Thanks for the help :)
https://gnosisdevelopment.com/office/list.json
{
"title": "Welcome to our office",
"description": "Your smart office assistant",
"office_staff": [
{ "staff_name": "Dr. Bob"},
{ "staff_name": "Dr. Xavior"},
{ "staff_name": "Dr. Sanchez"},
{ "staff_name": "Dr. Robert"},
{ "staff_name": "Dr. Albert"}
]
}
UPDATE with new datasource load:
import React, { Component } from 'react';
import { ActivityIndicator, ListView, Text, View, StyleSheet,TouchableOpacity, FlatList } from 'react-native';
export default class Office extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: [],
}
}
componentDidMount() {
return fetch('https://gnosisdevelopment.com/office/list.json')
.then((response) => response.json())
.then((responseJson) => {
// just setState here e.g.
this.setState({ dataSource: responseJson.office_staff, isLoading:false,});
})
.catch((error) => {
console.error(error);
});
}
render() {
if (this.state.isLoading) {
return (
<View style={{flex: 1, paddingTop: 20}}>
<ActivityIndicator />
</View>
);
}
return (
<View style={styles.container}>
<FlatList
data={this.state.dataSource}
renderItem={({item}) =><Text style={styles.touchButtonText}>{item.staff_name}</Text>
}
keyExtractor={(item, index) => index}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex:1,
alignItems: 'center',
alignContent:'center',
flexDirection: 'row',
flexWrap:'wrap',
justifyContent:'center',
},
touchButton:{
alignSelf:'center',
backgroundColor:'#2980b9',
paddingVertical: 25,
width:295,
margin:15,
},
touchButtonText:{
textAlign:'center',
color:'#ffffff',
fontWeight:'bold'
},
})
Final working version:
import React, { Component } from 'react';
import { ActivityIndicator, Text, View, StyleSheet,TouchableOpacity, FlatList } from 'react-native';
export default class Office extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: [],
}
}
componentDidMount() {
return fetch('https://gnosisdevelopment.com/office/list.json')
.then((response) => response.json())
.then((responseJson) => {
// just setState here e.g.
this.setState({ dataSource: responseJson.office_staff,isLoading: false });
})
.catch((error) => {
console.error(error);
});
}
render() {
if (this.state.isLoading) {
return (
<View style={{flex: 1, paddingTop: 20}}>
<ActivityIndicator />
</View>
);
}
return (
<View style={styles.container}>
<FlatList
data={this.state.dataSource}
renderItem={({item}) =><Text>{item.staff_name}</Text>}
keyExtractor={(item, index) => index}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex:1,
alignItems: 'center',
alignContent:'center',
flexDirection: 'row',
flexWrap:'wrap',
justifyContent:'center',
},
touchButton:{
alignSelf:'center',
backgroundColor:'#2980b9',
paddingVertical: 25,
width:295,
margin:15,
},
touchButtonText:{
textAlign:'center',
color:'#ffffff',
fontWeight:'bold'
},
})
You don't need to provide a dataSource like that.
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: [],
}
}
componentDidMount() {
return fetch('https://gnosisdevelopment.com/office/list.json')
.then((response) => response.json())
.then((responseJson) => {
// just setState here e.g.
this.setState({
dataSource: responseJson.office_staff,
isLoading: false,
});
})
.catch((error) => {
console.error(error);
});
}