React Native Download JSON but not displaying in Flatlist - json

I am trying to download the JSON. React Native is downloading the json but I am not sure why Flatlist is not displaying the items. If I change the data={dummyData} in flatlist to data={MyList} then, the flatlist is able to display.
let viewableItemsChanged = null;
const dummyData = GrabData('http://hunterdata.serveblog.net/10record.json');
const MyList = [
{"id":"0","title":"MyBook0","url":"URLBook-0","image":"image-0" },
{"id":"1","title":"MyBook1","url":"URLBook-1","image":"image-1" },
{"id":"2","title":"MyBook2","url":"URLBook-2","image":"image-2" },
{"id":"3","title":"MyBook3","url":"URLBook-3","image":"image-3" },
{"id":"4","title":"MyBook4","url":"URLBook-4","image":"image-4" },
{"id":"5","title":"MyBook5","url":"URLBook-5","image":"image-5" }];
async function GrabData(TheURL) {
let abc = [];
try {
let response = await fetch(TheURL, {headers: {'Cache-Control' : 'no-cache'}});
let responseJson = await response.json();
console.log(responseJson);
return responseJson;
} catch (error) {
console.error(error);
}
}
const renderItem = ({item}) => {
return <View><Text>{item.title}</Text></View>
}
const List = () => {
return (
<FlatList
style={styles.list}
data={dummyData}
renderItem={renderItem}
/>
)
};

there is an issue with your code. you are calling the async function without await keyword. so it returns undefine response like this. {"_U": 0, "_V": 0, "_W": null, "_X": null}
Please Try this solution.
import React, { useEffect , useState } from 'react';
import { SafeAreaView, View, FlatList, StyleSheet, Text, StatusBar } from 'react-native';
const Item = ({ title }) => (
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);
const App = () => {
const [data, setData] = useState([])
useEffect(() => {
apicall();
},[])
const apicall = async () => {
let dd = await GrabData("http://hunterdata.serveblog.net/10record.json");
setData(dd)
}
const GrabData = async (TheURL) => {
try {
let response = await fetch(TheURL, {headers: {'Cache-Control' : 'no-cache'}});
let responseJson = await response.json();
return responseJson;
} catch (error) {
console.error(error);
}
}
const renderItem = ({ item }) => (
<Item title={item?.title} />
);
return (
<SafeAreaView style={styles.container}>
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={item => item?.id}
/>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: StatusBar.currentHeight || 0,
},
item: {
backgroundColor: '#f9c2ff',
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
},
title: {
fontSize: 32,
},
});
export default App;

You should activate the functions in componentDidMount also try states instead of const

Related

Trying to retrive JSON Array through fetch in react native but JSON parse error:Unreconised token "<"

In the code,i am fetching the token from expo-secure-store,later fetching the API data from fetchdata function.But unfortunately error "unrecognized token" is displayed.
After the error is displayed,the API call returns JSON Array data.Unable to do data map in react native to TradeCard Component.
import { StatusBar } from 'expo-status-bar';
import {React,useState,useEffect} from 'react';
import TradeCard from './TradeCard';
import { StyleSheet, Text, View,TextInput,TouchableOpacity,ScrollView,ActivityIndicator } from 'react-native';
import * as SecureStore from 'expo-secure-store';
export default function Trades()
{
const [ data,setData] = useState([]);
const [ isLoading,setLoading] = useState(true);
const [user,setUser] = useState('');
const [token,setToken] = useState('');
const fetchTokens = async () => {
try {
const user = await SecureStore.getItemAsync('user');
const token = await SecureStore.getItemAsync('token');
setUser(user);
setToken(token);
if (user && token)
{
fetchData();
}
else
{
}
} catch (e) {
alert('Error',e);
}
}
useEffect(()=>{ fetchTokens()},[]);
const fetchData = async () => {
setLoading(true);
fetch('https://tradecoaster.herokuapp.com/api/v1/listTrades/'+user+'/',
{
method:'GET',
headers:{
'Accept':'application/json',
'Content-Type':'application/json',
'Authorization':'token '+token
}
})
.then(res => res.json())
.then((res)=>{
console.log('Data',res);
setData(res);
setLoading(false);
})
.catch((error)=>{
setLoading(false);
alert(error);
console.error("Error",error);
});
}
return(
<ScrollView>
<View>
{isLoading && data.length==0 ? <ActivityIndicator size="large" color="#0000ff" /> :
<Text>No Trades</Text>
}
</View>
</ScrollView>
);
}```

React Native Download multiple JSON and combine

I am trying to download multiple JSON and combine them together in the variable and display them in a flatlist. But I am only seeing contents from only 1 JSON. How do we do multiple download and combine the result ? Is there a better way to do this ? Am I downloading it the correct way ?
export default class CategoryScreen extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: [],
AllNews: [],
}
}
componentDidMount(){
this.GrabData('http://hunterdata.serveblog.net/t-computerworld.json');
this.GrabData('http://hunterdata.serveblog.net/t-thestar.json');
}
async GrabData(TheURL) {
let tmpData = [];
try{
const response = await fetch(TheURL, {headers: {'Cache-Control' : 'no-cache'}});
const data = await response.json();
tmpData = data;
if ((this.state.dataSource.length) = 0) {
this.setState({ dataSource: tmpData });
} else {
let tmpData1 = this.state.dataSource;
tmpData = [...tmpData1, ...data];
this.setState({ isLoading: false, dataSource: tmpData})
}
} catch (error) {
console.error(error);
}
}
render() {
if (this.state.isLoading) {
return (
<View>
<ActivityIndicator />
</View>
)
} else {
let mydata = this.state.dataSource;
return (
<View style={styles.container}>
<FlatList
data={mydata}
renderItem={({item}) => <Text style={styles.text}>{item.title}</Text>}
/>
</View>
);
}
}
}
if ((this.state.dataSource.length) = 0) {
Should be
if ((this.state.dataSource.length) === 0) {
You are so right. Thank you. This solved my issue.
if ((this.state.dataSource.length) === 0) {

How to load data onto a React State from an API instead of local json file?

So as part of my project I'm trying to ammend this boilerplate of React-Pdf-Highlighter to accept pdf highlights from flask-api instead of a local file( the example came with a local/json import) ..
I have tried to check with console.log the fetch is not the problem, but I feel for somereason the 'testHighlights' state is not what it should be .
<<App.js>>
// #flow
/* eslint import/no-webpack-loader-syntax: 0 */
import React, { Component } from "react";
import PDFWorker from "worker-loader!pdfjs-dist/lib/pdf.worker";
import {
PdfLoader,
PdfHighlighter,
Tip,
Highlight,
Popup,
AreaHighlight,
setPdfWorker
} from "react-pdf-highlighter";
import Spinner from "./Spinner";
import Sidebar from "./Sidebar";
import testHighlights from "./test-highlights";
import type {
T_Highlight,
T_NewHighlight
} from "react-pdf-highlighter/src/types";
import "./style/App.css";
setPdfWorker(PDFWorker);
type Props = {};
type State = {
url: string,
highlights: Array<T_Highlight>
};
const getNextId = () => String(Math.random()).slice(2);
const parseIdFromHash = () =>
document.location.hash.slice("#highlight-".length);
const resetHash = () => {
document.location.hash = "";
};
const HighlightPopup = ({ comment }) =>
comment.text ? (
<div className="Highlight__popup">
{comment.emoji} {comment.text}
</div>
) : null;
const PRIMARY_PDF_URL = "https://arxiv.org/pdf/1708.08021.pdf";
const SECONDARY_PDF_URL = "https://arxiv.org/pdf/1604.02480.pdf";
const searchParams = new URLSearchParams(document.location.search);
const initialUrl = searchParams.get("url") || PRIMARY_PDF_URL;
class App extends Component<Props, State> {
state = {
url: initialUrl,
highlights: testHighlights[initialUrl]
? [...testHighlights[initialUrl]]
: []
};
state: State;
resetHighlights = () => {
this.setState({
highlights: []
});
};
toggleDocument = () => {
const newUrl =
this.state.url === PRIMARY_PDF_URL ? SECONDARY_PDF_URL : PRIMARY_PDF_URL;
this.setState({
url: newUrl,
highlights: testHighlights[newUrl] ? [...testHighlights[newUrl]] : []
});
};
scrollViewerTo = (highlight: any) => {};
scrollToHighlightFromHash = () => {
const highlight = this.getHighlightById(parseIdFromHash());
if (highlight) {
this.scrollViewerTo(highlight);
}
};
componentDidMount() {
window.addEventListener(
"hashchange",
this.scrollToHighlightFromHash,
false
);
}
getHighlightById(id: string) {
const { highlights } = this.state;
return highlights.find(highlight => highlight.id === id);
}
addHighlight(highlight: T_NewHighlight) {
const { highlights } = this.state;
console.log("Saving highlight", highlight);
this.setState({
highlights: [{ ...highlight, id: getNextId() }, ...highlights]
});
}
updateHighlight(highlightId: string, position: Object, content: Object) {
console.log("Updating highlight", highlightId, position, content);
this.setState({
highlights: this.state.highlights.map(h => {
const {
id,
position: originalPosition,
content: originalContent,
...rest
} = h;
return id === highlightId
? {
id,
position: { ...originalPosition, ...position },
content: { ...originalContent, ...content },
...rest
}
: h;
})
});
}
render() {
const { url, highlights } = this.state;
return (
<div className="App" style={{ display: "flex", height: "100vh" }}>
<Sidebar
highlights={highlights}
resetHighlights={this.resetHighlights}
toggleDocument={this.toggleDocument}
/>
<div
style={{
height: "100vh",
width: "75vw",
position: "relative"
}}
>
<PdfLoader url={url} beforeLoad={<Spinner />}>
{pdfDocument => (
<PdfHighlighter
pdfDocument={pdfDocument}
enableAreaSelection={event => event.altKey}
onScrollChange={resetHash}
// pdfScaleValue="page-width"
scrollRef={scrollTo => {
this.scrollViewerTo = scrollTo;
this.scrollToHighlightFromHash();
}}
onSelectionFinished={(
position,
content,
hideTipAndSelection,
transformSelection
) => (
<Tip
onOpen={transformSelection}
onConfirm={comment => {
this.addHighlight({ content, position, comment });
hideTipAndSelection();
}}
/>
)}
highlightTransform={(
highlight,
index,
setTip,
hideTip,
viewportToScaled,
screenshot,
isScrolledTo
) => {
const isTextHighlight = !Boolean(
highlight.content && highlight.content.image
);
const component = isTextHighlight ? (
<Highlight
isScrolledTo={isScrolledTo}
position={highlight.position}
comment={highlight.comment}
/>
) : (
<AreaHighlight
highlight={highlight}
onChange={boundingRect => {
this.updateHighlight(
highlight.id,
{ boundingRect: viewportToScaled(boundingRect) },
{ image: screenshot(boundingRect) }
);
}}
/>
);
return (
<Popup
popupContent={<HighlightPopup {...highlight} />}
onMouseOver={popupContent =>
setTip(highlight, highlight => popupContent)
}
onMouseOut={hideTip}
key={index}
children={component}
/>
);
}}
highlights={highlights}
/>
)}
</PdfLoader>
</div>
</div>
);
}
}
export default App;
<<test-highlights.js >>
const testHighlights =async () => {
const res= await fetch('http://127.0.0.1:5000/jsonapi')
const data =await res.json()
console.log(data)
this.state.testHighlights = data
return testHighlights;
}
export default testHighlights;
You can't assign state like this
this.state.testHighlights = data
You must use this.setState function to do it
this.setState({ testHighlights: data });
That is why your testHighlights state isn't what you was expected

MQTT Response with React Native

I am currently making an IoT App that I'm trying to connect to a raspberry pi using MQTT. I use the react_native_mqtt package. I use the code posted by simaAttar from here: How to use MQTT on React Native? . The problem I have it doesnt always update my code when I alter it and save. What I'm trying to achieve is to receive a JSON formatted string from the rasp and use that to fill a FlatList with react-native-elements ListItem. But the data received is undefined, even though yesterday I did have it working for a second, it won't work anymore now.
Any help is appreciated.
EDIT: this is the code (forgot to post it)
import React, {Component} from 'react';
import init from 'react_native_mqtt';
import AsyncStorage from '#react-native-community/async-storage';
import {
ActivityIndicator,
StyleSheet,
Text,
View,
FlatList,
TouchableOpacity,
TextInput,
Button,
Alert,
} from 'react-native';
import {ListItem} from 'react-native-elements';
init({
size: 10000,
storageBackend: AsyncStorage,
enableCache: true,
sync: {},
});
export default class AllPeople extends Component {
constructor() {
super();
this.onMessageArrived = this.onMessageArrived.bind(this);
this.onConnectionLost = this.onConnectionLost.bind(this);
const client = new Paho.MQTT.Client(
'onto.mywire.org',
8080,
'Client-' + Math.random() * 9999 + 1,
);
client.onMessageArrived = this.onMessageArrived;
client.onConnectionLost = this.onConnectionLost;
client.connect({
onSuccess: this.onConnect,
useSSL: false,
onFailure: (e) => {
console.log('Error: ', e);
},
});
this.state = {
message: [''],
data: [],
isLoading: true,
client,
messageToSend: '',
isConnected: false,
};
}
onConnect = () => {
console.log('Connected');
const {client} = this.state;
client.subscribe('/app/to/allpeople');
this.setState({
isConnected: true,
error: '',
isLoading: true,
messageToSend: 'allpeople',
});
this.sendMessage();
};
onMessageArrived(entry) {
console.log("Nieuwe Test 1:")
console.log("PayloadMEssage: "+entry.payloadMessage);
console.log("Payload tostring: "+entry.payloadMessage.toString())
//this.setState({data: entry, isLoading: false});
}
sendMessage = () => {
console.log('message send.');
var message = new Paho.MQTT.Message(this.state.messageToSend);
message.destinationName = '/app/from';
if (this.state.isConnected) {
this.state.client.send(message);
} else {
this.connect(this.state.client)
.then(() => {
this.state.client.send(message);
this.setState({error: '', isConnected: true});
})
.catch((error) => {
console.log(error);
this.setState({error: error});
});
}
};
onConnectionLost(responseObject) {
if (responseObject.errorCode !== 0) {
console.log('onConnectionLost:' + responseObject.errorMessage);
this.setState({error: 'Lost Connection', isConnected: false});
}
}
render() {
return (
<View style={styles.container}>
{this.state.isLoading ? (
<ActivityIndicator />
) : (
<FlatList
keyExtractor={keyExtractor}
data={this.state.data}
renderItem={Item}
/>
)}
</View>
);
}
}
const keyExtractor = (item, index) => login.username.toString();
const Item = ({item}) => {
return (
<TouchableOpacity>
<ListItem
title="TestTitle" //{item.results.name.first}
titleStyle={{fontWeight: 'bold'}}
leftIcon={<MCIcons name="account" size={36} color="dodgerblue" />}
subtitle={item.results.name.last}
rightTitle={item.results.registered.date}
rightTitleStyle={{fontSize: 14}}
chevron
bottomDivider
/>
</TouchableOpacity>
);
};
const styles = StyleSheet.create({
container: {
backgroundColor: '#F5FCFF',
},
});
I have managed to fix it by changing entry.payloadMessage to entry.payloadString. Apparentyly I changed it during the editing of my code.

How to fetch data from URL and then store it in AsyncStorage in React Native?

I'm trying to fetch data from URL and then store it in AsyncStorage in React Native.
This is screen where "magic" happens:
class CardsScreen extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: null,
}
}
componentDidMount() {
return fetch(REQUEST_URL)
.then((response) => response.json())
.then((responseData) => {
this.setState({
isLoading: false,
dataSource: responseData,
});
})
.catch((error) => {
console.log(error)
});
}
render() {
if (netStatus) {
if (this.state.isLoading) {
return (
<View style={styles.container}>
<ActivityIndicator/>
</View>
)
} else {
let data = this.state.dataSource.map((val, key) => {
return <View key={key} style={styles.itemWrapper}>
<View style={styles.titleWrapper}>
<Text style={styles.content}>{val.type}</Text>
<Text style={styles.title}>{val.title}</Text>
<Text style={styles.content}>{val.date}</Text>
</View>
<View style={styles.imageWrapper}>
<Image
style={styles.image}
source={{uri: val.image}}
/>
</View>
<View style={styles.contentWrapper}>
<Text style={styles.content}>{val.adress}</Text>
<Text style={styles.content}>{val.text}</Text>
</View>
</View>
})
return (
<ScrollView contentContainerStyle={styles.containerScroll}>
{data}
</ScrollView>
);
}
} else {
return <View style={styles.contentWrapper}>
<Text style={styles.content}>Not connected!</Text>
</View>
}
}
};
This code prints data if device is connected to internet.
What I need to do is if device is conneted to internet, fetch data from URL and store (or overwrite) it in AsyncStorage, and then print data on screen. If device is not connect to the internet just print data from AsyncStorage.
This is example of .json I call from URL:
[
{
"type": "Party",
"title": "New party comming to town!",
"adress": "New Yrok",
"date": "20. 4. 2019.",
"image": "https:\/\/some-url.com\/some-image.jpg",
"text": [
"Some description"
],
"_id": "events_1"
}
]
I can't find any similar solution, so I would be greatfull if someone has tutorial that could help me with this.
EDIT (little more of explenation):
This is what I want to do:
If device is connected to the internet, update AsyncStorage with data from URL and then display that new data in AsyncStorage. If device is not connected to the internet, just display data that is AsyncStorage. And there are multiple "events", not just one like in the example.
export default class BankDetails extends Component {
constructor(props) {
super(props)
this.state = {
userToken: null,
userData: {
nameOfBank: '',
account_umber: '',
account_holder_ame: ''
}
}
}
async componentDidMount () {
try {
let value = await AsyncStorage.getItem('userData')
let userDetails = JSON.parse(value)
if (userDetails !== null) {
let userData= Object.assign({}, this.state.userData)
userData.nameOfBank = userDetails.nameOfBank
userData.account_umber = userDetails.account_umber
userData.account_holder_ame = userDetails.account_holder_ame
this.setState({
userToken: userDetails.token,
userData
})
}
} catch (error) {
console.log(error)
}
}
onBankChange = (nameOfBank) => {
this.setState({userData: {...this.state.userData, nameOfBank:nameOfBank}})
}
saveBankDetailsEdit = () => {
const { nameOfBank,account_umber, account_holder_ame }= this.state.userData
let {userToken} = this.state
var formData = new FormData()
formData.append('bank', nameOfBank)
formData.append('account_number', account_umber)
formData.append('account_title', account_holder_ame)
fetch('http://xxxx/update', {
method: 'POST',
headers: {
'X-API-KEY': '123456',
'Authorization': userToken
},
body: formData
}).then(function (response) {
console.log(response)
AsyncStorage.getItem('userData').then(
data => {
data = JSON.parse(data)
data.nameOfBank = nameOfBank
data.account_umber = account_umber
data.account_holder_ame = account_holder_ame
AsyncStorage.setItem('userData', JSON.stringify(data))
}
)
let data = JSON.parse(response._bodyText)
Alert.alert(data.message)
})
.catch((error) => {
console.log(error)
})
.done()
}
This is how I have done my job. Hope this helps.
You need to store your response like this
note one thing when you set value into AsyncStorage you need to store as string JSON.stringify() value into storage.
onSave = async () => {
try {
await AsyncStorage.setItem("key", JSON.stringify(responseData));
Alert.alert('Saved', 'Successful');
} catch (error) {
Alert.alert('Error', 'There was an error.')
}
}
and when you get value from AsyncStorage you need to JSON.parse()
onSave = async () => {
try {
const storedValue = await AsyncStorage.getItem("key");
this.setState({ storedValue: JSON.parse(storedValue) });
} catch (error) {
Alert.alert('Error', 'There was an error.')
}
}
hope it will help you