How to get data from fetch inside a function in React Native - javascript

I am trying to fetch data from external api and show that on display. When I press button it calls function which console things normally but can't show returned value.
export default function HomeScreen() {
return (
<View style={styles.container}>
<Button title='show data' onPress={loadText}/>
<Text>{loadText}</Text>
</View>
);
function loadText(){
fetch('http://192.168.88.253:5000/read')
.then((response) => response.json())
.then((responseJson) => {
return (
console.log(responseJson.city)
);
})
.catch((error) => {
console.error(error);
});
}
}
If I understand it, loadText function must return responseJson.city value as a string.
How can I show it in <View> or <Text>?

export default function HomeScreen() {
constructor(props){
super(props);
this.state = {
city: ''
}
}
return (
<View style={styles.container}>
<Button title='show data' onPress={() => this.loadText()}/>
<Text>{this.state.city}</Text>
</View>
);
loadText(){
fetch('http://192.168.88.253:5000/read')
.then((response) => response.json())
.then((responseJson) => {
this.setState({city: responseJson.city});
})
.catch((error) => {
console.error(error);
});
}
}

you can use alert() to display the data.
alert is the popup which will be displayed on the mobile screen.
export default function HomeScreen() {
return (
<View style={styles.container}>
<Button title='show data' onPress={loadText}/>
<Text>{loadText}</Text>
</View>
);
function loadText(){
fetch('http://192.168.88.253:5000/read')
.then((response) => response.json())
.then((responseJson) => {
return (
alert(JSON.stringfy(responseJson.city))
);
})
.catch((error) => {
alert(JSON.stringfy(error));
});
}
}

Related

Fetch data from API using React Native

I'm trying to fetch data from the url below, but when I launch the code it returns the error: TypeError: undefined is not an object (evaluating 'res.data.hints'), and consequentially nothing happens, I've followed various tutorials and they seem to come up with this code.
States
constructor(props) {
super(props);
this.updateSearch();
this.state = {
data: [],
};
}
Function
updateSearch = () => {
const url = `https://api.edamam.com/api/food-database/v2/parser?ingr=b&app_id=000&app_key=00000&page=20`;
fetch(url)
.then((res) => res.json())
.then((res) => {
this.setState({
data: res.data.hints
});
})
.catch(error => {
console.log("error : "+ error)
});
};
Flatlist
<FlatList
data={this.state.data}
renderItem={({ item }) => (
<ListItem>
<TouchableOpacity>
<View>
<Text>{item.label}</Text>
<Text>{item.brand}</Text>
</View>
</TouchableOpacity>
</ListItem>
)}
keyExtractor={(item) => item.foodId}
/>
this.setState({
data: res.hints
});
Try this

React Native: How do I display a variable in a Text element once an async function has returned it?

The fetch function returns all the correct info; I know this because it all gets logged to the console, but the Text element never shows the pokemon name once the json data is saved into the Pokemon class. Im using expo btw.
export default function App() {
let Pokemon = {
getInfo: async (name) => {
name = name.toLowerCase();
const uri = `https://pokeapi.co/api/v2/pokemon/${name}`;
await fetch(uri)
.then(response => response.json())
.then(data => {
Pokemon.name = data.forms[0].name;
Pokemon.img = data.sprites.front_default;
})
.catch(error => {
if(error){
console.log(`Failed to find "${name}"`)
}
});
console.log(await Pokemon.name, await Pokemon.img)
}
}
const [value, onChangeText] = React.useState('Enter A Pokemon');
return (
<View style={styles.container}>
<Text style={styles.title}>{Pokemon.name}</Text>
<TextInput
style={styles.textBox}
clearTextOnFocus={true}
onChangeText={async text => {
onChangeText(text)
Pokemon.getInfo(text)
}}
value={value}
/>
<StatusBar style="auto" />
</View>
);
}
Call me cap'n hook:
export default function App() {
let Pokemon = {
getInfo: async (name) => {
name = name.toLowerCase();
const uri = `https://pokeapi.co/api/v2/pokemon/${name}`;
await fetch(uri)
.then(response => response.json())
.then(data => {
Pokemon.name = data.forms[0].name;
Pokemon.img = data.sprites.front_default;
})
.catch(error => {
if(error){
console.log(`Failed to find "${name}"`)
}
});
console.log(await Pokemon.name, await Pokemon.img)
}
}
const [value, onChangeText] = React.useState('Enter A Pokemon');
const [myText, setMyText] = React.useState("My Original Text");
return (
<View style={styles.container}>
<Text style={styles.title}>{myText}</Text>
<TextInput
style={styles.textBox}
clearTextOnFocus={true}
onChangeText={async text => {
onChangeText(text)
await Pokemon.getInfo(text)
setMyText(await Pokemon.name)
}}
value={value}
/>
<StatusBar style="auto" />
</View>
);
}

Connecting REST API in React Native

I am trying to learn how to connect APIs in React Native. I am using a sample API: https://reactnative.dev/movies.json
This is my code:
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
loading: true,
dataSource: [],
};
}
componentDidMount() {
return fetch("https://reactnative.dev/movies.json")
.then((response) => response.json())
.then((responseJson) => {
this.setState({
loading: false,
dataSource: responseJson.movies,
});
})
.catch((error) => console.log(error)); //to catch the errors if any
}
render() {
if (this.state.isLoading) {
return (
<View style={styles.container}>
<ActivityIndicator size="large" color="#0c9" />
</View>
);
} else {
let products = this.state.dataSource.map((val, key) => {
return (
<View key={key} style={styles.item}>
<Text>{val}</Text>
</View>
);
});
return (
<View style={styles.container}>
<Text>{products.title}</Text>
</View>
);
}
}
}
The problem occurs with my "products" variable. In debug mode, I was able to see the key and value pairs which were correct from the API. However, the products array is populated with objects rather than strings which are structured like this:
Object {$$typeof: Symbol(react.element), type: "RCTView", key: "0", …}
My code returns the following error: this.state.dataSource.map is not a function
EDIT:
The answer below worked for the API I was using. Now I am trying a different API structured like this:
{"prods":
{
"86400":{"slug":"86400","url":"/86400"},
"23andme":{"slug":"23andme","url":"/23andme"}
}}
I am having trouble with the mapping again. This returns an error:
return dataSource.map((val, key) => (
<View key={key} style={styles.item}>
<Text>{val.slug}</Text>
</View>
));
First, there is a small typo in your example. In your component's constructor you specify a loading state variable, but in your render function you're using isLoading. Second, you're not mapping over your data correctly. It just looks like you need to specify what aspects of each movie you care about in your render function. JSX can't handle displaying a full javascript object which is what <Text>{val}</Text> ends up being in your code. There are a few ways you can fix this. It's very common to just map over your results and display them directly.
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
loading: true,
dataSource: []
};
}
componentDidMount() {
return fetch("https://reactnative.dev/movies.json")
.then(response => response.json())
.then(responseJson => {
this.setState({
loading: false,
dataSource: responseJson.movies
});
})
.catch(error => console.log(error));
}
render() {
const { loading, dataSource } = this.state;
if (loading) {
return (
<View style={styles.container}>
<ActivityIndicator size="large" color="#0c9" />
</View>
);
}
return dataSource.map((movie, index) => (
<View key={movie.id} style={styles.item}>
<Text>{movie.title}</Text>
</View>
));
}
}
You could also pull this out to a renderMovies method, which might help since you are trying to display these in a styled container.
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
loading: true,
dataSource: []
};
}
componentDidMount() {
return fetch("https://reactnative.dev/movies.json")
.then(response => response.json())
.then(responseJson => {
this.setState({
loading: false,
dataSource: responseJson.movies
});
})
.catch(error => console.log(error));
}
renderMovies() {
const { dataSource } = this.state;
return dataSource.map((movie, index) => (
<View key={movie.id} style={styles.item}>
<Text>{movie.title}</Text>
</View>
));
}
render() {
const { loading } = this.state;
if (loading) {
return (
<View style={styles.container}>
<ActivityIndicator size="large" color="#0c9" />
</View>
);
}
return (
<View style={styles.container}>
{this.renderMovies()}
</View>
);
}
}
I have used Object.values() to restructure the object into an array
componentDidMount() {
return fetch("https://reactnative.dev/movies.json")
.then((response) => response.json())
.then((responseJson) => {
this.setState({
loading: false,
dataSource: Object.values(responseJson.movies), //changed this
});
})
.catch((error) => console.log(error));
}
Try simple way. This code uses modern React practice and helps you to brush up your React skills in general. Give a try.
import React, {useState, useEffect} from 'react';
import { Text, View, StyleSheet } from 'react-native';
import axios from 'axios'; //for fetching data
export default function App() {
//React Hook for state
const [ data, setData ] = useState ([]);
//React Hook Instead Of ComponentDidMount
useEffect(() => {
const fetchData = async () => {
const result = await axios(
"https://reactnative.dev/movies.json",
);
setData(result.data.movies);
};
fetchData();
}, []);
return (
<View>
<Text>{JSON.stringify(data)}</Text>
</View>
);
}

How to Fetch APIs and Print first element in response Array?

My React Native app fetch API data and I need to print the first index of response but it's not, and gets all of the "ozone" for example in all child of the parent Array and when I print val[0] when Mapping I have nothing printed
My Code|
export default class App extends Component {
constructor(props) {
super(props);
this.state = { isLoading: true, dataSource: null };
}
async componentDidMount() {
let API_WEATHER =
"https://api.weatherbit.io/v2.0/forecast/daily?city=Raleigh,NC&key={API_KEY}";
fetch(API_WEATHER)
.then(response => response.json())
.then(responseJson => {
console.log(responseJson.data);
this.setState({
isLoading: false,
dataSource: responseJson.data
});
})
.catch(error => {
console.log(error);
});
}
render() {
if (this.state.isLoading) {
return (
<View style={{ flex: 1, padding: 20 }}>
<ActivityIndicator size="large" />
</View>
);
}
let weather= this.state.dataSource.map((val, key) => {
return (
<Text key={key}>
{val.ozone}
</Text>
);
});
return (
<ScrollView style={styles.container}>
<ScrollView>
<View>
<Text>{weather}</Text>
</View>
</ScrollView>
</ScrollView>
);
}
In this part of the code when i log the respone JSON obj
.then(responseJson => {
console.log(responseJson.data);
console.log(responseJson.data[0]);
console.log(responseJson.data[0].datetime);
}
i have what i need, but when print them in View i have Erroe
look at the Images
You're probably the first key of the object.
obj[Object.keys(obj)[0]];
Also, you can use
Try the for … in loop and break after the first iteration
for (var prop in object) {
// object[prop]
break;
}

React Native function bind parameters

I am trying to render a list which calls a function to render the rows, but how can I pass the paramater data to the function/handler?
The data is in json style.
I tried many things but I always get an error back, what am I doing wrong?
This the code:
componentDidMount() {
fetch('http://link/json.php', {
method: 'GET'
})
.then((response) => response.json())
.then((responseJson) => {
dataJson = responseJson;
this.setState({
preLoad: true
});
})
.catch((error) => {
});
}
renderRows(item){
if(item.type == 2){
return(
<ListItem>
<Thumbnail square size={80} source={{ uri: 'item.image' }} />
<Body>
<Text>{item.title}</Text>
<Text note>{item.desc}</Text>
</Body>
</ListItem>
)
}
}
renderMenu(){
if(this.state.preLoad){
return(
<List dataArray={dataJson}
renderRow={(item) =>
this.renderRows().bind(this,item)
}>
</List>
)
}else{
return(
<Body>{shimmerRows}</Body>
)
}
}
render() {
return (
<Container style={styles.container}>
{this.renderMenu()}
</Container>
);
}
It seems you just need to save your response to the state.
this.setState({
preLoad: true,
dataJson: responseJson,
});
And do the binding correctly.
<List dataArray={this.state.dataJson}
renderRow={(item) => this.renderRows.bind(this,item)}>
</List>

Categories

Resources