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

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>
);
}```

Related

React Native Download JSON but not displaying in Flatlist

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

Trying to fetch a specific record in JSON file

I am trying to fetch just one record from my JSON file, the JSON file is in the public folder
I set up a codesandbox https://codesandbox.io/live/7gu09fv
What is happening now is that it just returns the first record from the JSON and isn't matching the id to pageId
import React, { useState, useEffect } from 'react';
import {
useLocation
} from "react-router-dom";
function FetchContent( { pageId } ) {
const [page, setPage] = useState([]);
useEffect(() => {
fetch("pages.json" ,{
headers : {
'Content-Type': 'application/json',
'Accept': 'application/json'
}
})
.then(res => res.json())
.then(json =>{
setPage(json)
}
)
}, []);
const found = page.find(id => id = { pageId });
if (!found) return <div />;
return (
<>
<h1 key={found.id}>{found.title.rendered}: {found.id} : {pageId}</h1>
</>
);
}
function Page() {
const { state: { pageId } } = useLocation();
return (
<div className="container-fluid">
<FetchContent pageId={pageId} />
</div>
);
}
export default Page;
import React, { useState, useEffect } from "react";
import { useLocation } from "react-router-dom";
function FetchContent({ pageId }) {
const [foundItem, setFoundItem] = useState();
useEffect(() => {
fetch("pages.json", {
headers: {
"Content-Type": "application/json",
Accept: "application/json"
}
})
.then((res) => res.json())
.then((json) => {
const found = json.find(({id}) => (id === pageId));
setFoundItem(found);
});
}, [pageId]);
if (!foundItem) return <div />;
return (
<>
<h1 key={foundItem.id}>
{foundItem.title && foundItem.title.rendered ? foundItem.title.rendered: ''}: {foundItem.id} : {pageId}
</h1>
</>
);
}
function Page() {
const location = useLocation();
const [pageId, setPageId] = useState(null);
useEffect(()=> {
if(location.state){
setPageId(parseInt(location.state.pageId, 10));
}
}, [location]);
return (
<div className="container-fluid">
<FetchContent pageId={pageId} />
</div>
);
}
export default Page;
Try this:
const found = page.find(obj => obj.id === pageId);

How to pass data from a function in react native component

I have created a Banner Component in React Native and now im trying to add data from a function (seperate .js file) in this component. I want to fetch the data on the inital load from my Home Screen but i dont know how to pass the data from my function. I hope you can help me.
This is my code:
home.js
export function HomeScreen() {
{/*This will cause an error*/}
const [item, setItem] = React.useState([]);
React.useEffect(() => {
{/*Function where i fetch my Data from API */}
getbannerdata().then(res => {
setItem(res)
})
console.log(item)
}, [])
return (
<SafeAreaProvider>
<SafeAreaView style={style.container}>
<View>
{/*Banner Component with Data param*/}
<Banner data={item} />
<Text>Home</Text>
</View>
</SafeAreaView>
</SafeAreaProvider>
);
}
My function:
bannerdata.js
export const getbannerdata = () => {
const [data, setData] = React.useState([])
console.log('Test')
fetch('http://192.168.178.46:8000/intranet/messages/', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
.then(res => res.json())
.then(res => {
console.log(res)
setData(res)
})
.catch(error => console.log(error));
return data;
};
I hope you can help me.
You should use useState in your component only not in the function where you fetch data.
bannerdata.js
export const getbannerdata = () => {
return fetch('http://192.168.178.46:8000/intranet/messages/', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
};
home.js
import { getbannerdata } from './bannerdata'; //import getbannerdata function and you should provide the path of bannerdata.js
export function HomeScreen() {
const [item, setItem] = React.useState([]);
React.useEffect(() => {
{/*Function where i fetch my Data from API */}
getbannerdata()
.then(res => res.json())
.then(res => {
console.log(res)
setItem(res);
});
.catch(error => console.log(error));
}, []);
return (
<SafeAreaProvider>
<SafeAreaView style={style.container}>
<View>
{/*Banner Component with Data param*/}
<Banner data={item} />
<Text>Home</Text>
</View>
</SafeAreaView>
</SafeAreaProvider>
);
}
Thank you for your help.
This is my final solution.
Its a little bit different but now it works as expected
bannerdata.js
import * as React from 'react';
function getbannerdata(){
return fetch ('http://192.168.178.46:8000/intranet/messages/', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
.then((res) => res.json())
.then((resData) => {
return resData;
})
.catch(error => console.log(error))
};
export { getbannerdata }
home.js
import {getbannerdata} from './home/bannerdata.js';
export function HomeScreen() {
const [item, setItem] = React.useState([]);
React.useEffect(() => {
getbannerdata()
.then(res => setItem(res))
}, []);
return (
<SafeAreaProvider>
<SafeAreaView style={style.container}>
<View>
{/*Banner Component with Data param*/}
<Banner data={item} />
<Text>Home</Text>
</View>
</SafeAreaView>
</SafeAreaProvider>
);
}

How to avoid flash before entering next route with loading in react router?

I would like to use prepare to prepare next page before entering route and at this point a loading page is shown.
I have tried to use useLocation and useEffect but next page will flash in before loading page is shown.
const [loading, setLoading] = useState(true);
const location = useLocation(); // react-router
useEffect(() => {
setLoading(true);
setTimeout(() => {
prepare(() => setLoading(false)); // callback when `prepare` is complete
}, 0);
}, [location.pathname, prepare, setLoading]);
return (
<Switch>
{routes.map((route) => (
<Route
key={route.path}
path={route.path}
render={() => loading ? '' : <route.component />}
/>
))}
</Switch>
);
Currently I am using a dirty solution DelayedComponent
const DelayedComponent = (props) => {
const { component } = props;
const [show, setShow] = useState(false);
useEffect(() => {
const timeout = setTimeout(() => {
setShow(true);
}, 1000);
return () => {
clearTimeout(timeout);
}
}, []);
return show ? createElement(component) : <div />;
};
I am not sure, that i understood your problem correctly, but i will try to suggest something
It's your router:
<Switch>
{routes.map(({ path, component: Component }) => (
<Route
exact
key={path}
path={path}
>
<Component />
</Route>
))}
</Switch>
then your any component
// Users.js
import React from 'react';
import useFetchUsers from './useFetchUsers';
const Users = () => {
const { isLoadingUsers, users } = useFetchUsers();
if (isLoadingUsers) {
return <LoadingWhatEverComponent />
}
return (
<div>{users.map((user) => user.name)}</div>
)
}
Before users are not loaded you will show loading screen
// useFetchUsers.js
import { useCallback, useState, useEffect } from 'react';
export default () => {
const [isLoading, setIsLoading] = useState(true);
const [users, setUsers] = useState([]);
const fetchUsers = useCallback(async () => {
try {
const response = await axios(...);
setUsers(response.data.users);
} catch (error) {
console.error(error);
setUsers([]);
} finally {
setLoading(false);
}
}, [])
useEffect(() => {
fetchUsers();
}, [])
return {
isLoadingUsers: isLoading,
users
}
}
as a result, before fetchUsers is not over, you can see only loading component

How can I turn a function used in many components into its own component which I can reuse across the app?

I have a fetch request used on multiple pages, and would like to turn it into a component to simply call in whenever it's needed. This is proving to be harder than I thought, and it's bring up a number of issues.
I have tried using the wrappedComponent function but not sure if that's the solution as it's still not working. It's now saying that the fetchPosts class constructor cannot be invoked without new.
const that = this;
fetch ('/testrouter')
.then (response => {
return response.json();
}).then(jsonData => {
that.setState({posts:jsonData})
}).catch(err => {
console.log('Error fetch posts data '+err)
});
}
This is what I want to turn into a component, so that I can just call it by it's name from another one inside componentDidMount. I have tried doing this:
function fetchPosts(WrappedComponent) {
class FetchPosts extends Component {
constructor(props) {
super(props)
this.state = {
posts: []
}
}
fetchAllPosts() {
const that = this;
fetch ('/testrouter')
.then (response => {
return response.json();
}).then(jsonData => {
that.setState({posts:jsonData})
}).catch(err => {
console.log('Error fetch posts data '+err)
});
}
render() {
return (<WrappedComponent
fetchAllPosts = {this.fetchAllPosts})
/>);
}
}
return FetchPosts;
}
export default fetchPosts
Then importing it and calling it with fetchPosts but it's not working.
I was hoping I would be able to create a component, add the code then import the component, but this is not working.
You might want to create a custom hook to do this:
useFetch.jsx
import React, { useState, useEffect } from 'react'
const useFetch = (url) =>
const [state, setState] = useState({ loading: true, data: null, error: null })
useEffect(() => {
fetch(url)
.then(res => res.json())
.then(data => setState(state => ({ ...state, loading: false, data }))
.catch(error => setState(state => ({ ...state, loading: false, error }))
},[])
return state
}
export default useFetch
MyComponent.jsx
import React from 'react'
import useFetch from './useFetch.jsx'
const MyComponent = () => {
const data = useFetch('/testrouter')
return (<>
{ data.loading && "Loading..." }
{ data.error && `There was an error during the fetch: {error.message}` }
{ data.data && <Posts posts={data.data}/> }
</>)
}